{
    "version": "https://jsonfeed.org/version/1",
    "title": "Fahri NH Blog",
    "home_page_url": "https://fahri.blog/posts/",
    "description": "Fahri NH Blog",
    "items": [
        {
            "id": "https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/",
            "content_html": "<p>We will build a web application that supports local db synced with remote db. This post is a continuation from the previous post: <a class=\"\" href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/\">How to Build WatermelonDB Sync Backend in Elixir</a>.</p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"installing-dependencies\">Installing Dependencies<a href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/#installing-dependencies\" class=\"hash-link\" aria-label=\"Direct link to Installing Dependencies\" title=\"Direct link to Installing Dependencies\" translate=\"no\">​</a></h3>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token builtin class-name\">cd</span><span class=\"token plain\"> assets</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">npm</span><span class=\"token plain\"> i react react-dom uuid @nozbe/watermelondb @nozbe/with-observables</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">npm</span><span class=\"token plain\"> i </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-D</span><span class=\"token plain\"> @babel/preset-react @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties @babel/plugin-transform-runtime</span><br></div></code></pre></div></div>\n<p>Configure <code>assets/.babelrc</code>:</p>\n<div class=\"language-js codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-js codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token string-property property\" style=\"color:#36acaa\">\"presets\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token string\" style=\"color:#e3116c\">\"@babel/preset-env\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"@babel/preset-react\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token string-property property\" style=\"color:#36acaa\">\"plugins\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"@babel/plugin-proposal-decorators\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> </span><span class=\"token string-property property\" style=\"color:#36acaa\">\"legacy\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">true</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"@babel/plugin-proposal-class-properties\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> </span><span class=\"token string-property property\" style=\"color:#36acaa\">\"loose\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">true</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">          </span><span class=\"token string\" style=\"color:#e3116c\">\"@babel/plugin-transform-runtime\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">           </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">             </span><span class=\"token string-property property\" style=\"color:#36acaa\">\"helpers\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">true</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">             </span><span class=\"token string-property property\" style=\"color:#36acaa\">\"regenerator\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">           </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"lets-code\">Let's Code<a href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/#lets-code\" class=\"hash-link\" aria-label=\"Direct link to Let's Code\" title=\"Direct link to Let's Code\" translate=\"no\">​</a></h3>\n<p>Remove entirely <code>lib/blog_app_web/templates/page/index.html.eex</code> and replace it with this code:</p>\n<div class=\"language-markup codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-markup codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">div</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">id</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">blog-app</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag punctuation\" style=\"color:#393A34\">/&gt;</span><br></div></code></pre></div></div>\n<p>All frontend code related to blog app will be located in <code>assets/js/blog</code>.\nSo, we will import entry point of blog app in <code>assets/js/app.js</code>:</p>\n<div class=\"language-js codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-js codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\">// assets/js/app.js</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"../css/app.scss\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"phoenix_html\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"./blog\"</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"setup-database\">Setup <code>Database</code><a href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/#setup-database\" class=\"hash-link\" aria-label=\"Direct link to setup-database\" title=\"Direct link to setup-database\" translate=\"no\">​</a></h3>\n<div class=\"language-jsx codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-jsx codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\">// assets/js/blog/index.js</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports maybe-class-name\">React</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'react'</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">{</span><span class=\"token imports\"> render </span><span class=\"token imports punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'react-dom'</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">{</span><span class=\"token imports\"> </span><span class=\"token imports maybe-class-name\">Database</span><span class=\"token imports\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'@nozbe/watermelondb'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports maybe-class-name\">LokiJSAdapter</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'@nozbe/watermelondb/adapters/lokijs'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports maybe-class-name\">DatabaseProvider</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'@nozbe/watermelondb/DatabaseProvider'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports\">schema</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'./model/schema'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports maybe-class-name\">Post</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'./model/Post'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports maybe-class-name\">App</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'./App'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> adapter </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\">LokiJSAdapter</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  schema</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token literal-property property\" style=\"color:#36acaa\">useWebWorker</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">false</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token literal-property property\" style=\"color:#36acaa\">useIncrementalIndexedDB</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">true</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token function-variable function\" style=\"color:#d73a49\">onIndexedDBVersionChange</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token function\" style=\"color:#d73a49\">checkIfUserIsLoggedIn</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token dom variable\" style=\"color:#36acaa\">window</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">location</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">reload</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> database </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\">Database</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  adapter</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token literal-property property\" style=\"color:#36acaa\">modelClasses</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token maybe-class-name\">Post</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token literal-property property\" style=\"color:#36acaa\">actionsEnabled</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">true</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> rootElement </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token dom variable\" style=\"color:#36acaa\">document</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">getElementById</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">'blog-app'</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:#d73a49\">render</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag class-name\" style=\"color:#00009f\">DatabaseProvider</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">database</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">database</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">    </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag class-name\" style=\"color:#00009f\">App</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag punctuation\" style=\"color:#393A34\">/&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">  </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag class-name\" style=\"color:#00009f\">DatabaseProvider</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  rootElement</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><br></div></code></pre></div></div>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"schema\">Schema<a href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/#schema\" class=\"hash-link\" aria-label=\"Direct link to Schema\" title=\"Direct link to Schema\" translate=\"no\">​</a></h4>\n<div class=\"language-jsx codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-jsx codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\">// assets/js/blog/model/schema.js</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">{</span><span class=\"token imports\"> appSchema</span><span class=\"token imports punctuation\" style=\"color:#393A34\">,</span><span class=\"token imports\"> tableSchema </span><span class=\"token imports punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'@nozbe/watermelondb'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> mySchema </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">appSchema</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token literal-property property\" style=\"color:#36acaa\">version</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token literal-property property\" style=\"color:#36acaa\">tables</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:#d73a49\">tableSchema</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token literal-property property\" style=\"color:#36acaa\">name</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'posts'</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token literal-property property\" style=\"color:#36acaa\">columns</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">name</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'title'</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">type</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'string'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">name</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'content'</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">type</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'string'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">name</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'likes'</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">type</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'number'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">name</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'created_at'</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">type</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'number'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">name</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'updated_at'</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">type</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'number'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">export</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">default</span><span class=\"token plain\"> mySchema</span><br></div></code></pre></div></div>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"model\">Model<a href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/#model\" class=\"hash-link\" aria-label=\"Direct link to Model\" title=\"Direct link to Model\" translate=\"no\">​</a></h4>\n<div class=\"language-jsx codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-jsx codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\">// assets/js/blog/model/Post.js</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">{</span><span class=\"token imports\"> </span><span class=\"token imports maybe-class-name\">Model</span><span class=\"token imports\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'@nozbe/watermelondb'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">{</span><span class=\"token imports\"> field</span><span class=\"token imports punctuation\" style=\"color:#393A34\">,</span><span class=\"token imports\"> date</span><span class=\"token imports punctuation\" style=\"color:#393A34\">,</span><span class=\"token imports\"> readonly </span><span class=\"token imports punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'@nozbe/watermelondb/decorators'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">export</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">default</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">class</span><span class=\"token plain\"> </span><span class=\"token class-name\">Post</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">extends</span><span class=\"token plain\"> </span><span class=\"token class-name\">Model</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">static</span><span class=\"token plain\"> table </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'posts'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    @</span><span class=\"token function\" style=\"color:#d73a49\">field</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">'title'</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> title</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    @</span><span class=\"token function\" style=\"color:#d73a49\">field</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">'content'</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> content</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    @</span><span class=\"token function\" style=\"color:#d73a49\">field</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">'likes'</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> likes</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    @readonly @</span><span class=\"token function\" style=\"color:#d73a49\">date</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">'created_at'</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> createdAt</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    @readonly @</span><span class=\"token function\" style=\"color:#d73a49\">date</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">'updated_at'</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> updatedAt</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"appjs\"><code>App.js</code><a href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/#appjs\" class=\"hash-link\" aria-label=\"Direct link to appjs\" title=\"Direct link to appjs\" translate=\"no\">​</a></h3>\n<p><img decoding=\"async\" loading=\"lazy\" alt=\"BlogApp Mockup\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGRhdGEtZGlhZ3JhbS10eXBlPSJTQUxUIiBzdHlsZT0id2lkdGg6MzU1cHg7aGVpZ2h0OjIyMnB4O2JhY2tncm91bmQ6I0ZGRkZGRjsiIHdpZHRoPSIzNTVweCIgaGVpZ2h0PSIyMjJweCIgdmlld0JveD0iMCAwIDM1NSAyMjIiIHpvb21BbmRQYW49Im1hZ25pZnkiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiIGNvbnRlbnRTdHlsZVR5cGU9InRleHQvY3NzIj48P3BsYW50dW1sIDEuMjAyNi45Pz48ZGVmcy8+PGcgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGxlbmd0aEFkanVzdD0ic3BhY2luZyI+PHRleHQgeD0iNyIgeT0iNDYuODY3IiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjEyIiB0ZXh0TGVuZ3RoPSIyNS42OTkiPlRpdGxlPC90ZXh0Pjx0ZXh0IHg9IjEyNSIgeT0iNDYuODY3IiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjEyIj7CoDwvdGV4dD48bGluZSB4MT0iMTIzIiB5MT0iNDkuMzk4IiB4Mj0iMTY2IiB5Mj0iNDkuMzk4IiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjEyMyIgeTE9IjQ2LjM5OCIgeDI9IjEyMyIgeTI9IjQ4LjM5OCIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIxNjYiIHkxPSI0Ni4zOTgiIHgyPSIxNjYiIHkyPSI0OC4zOTgiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48dGV4dCB4PSI3IiB5PSI2NSIgZmlsbD0iIzAwMCIgZm9udC1zaXplPSIxMiIgdGV4dExlbmd0aD0iNDYuMjMiPkNvbnRlbnQ8L3RleHQ+PHRleHQgeD0iMTI1IiB5PSI2NSIgZmlsbD0iIzAwMCIgZm9udC1zaXplPSIxMiI+wqA8L3RleHQ+PGxpbmUgeDE9IjEyMyIgeTE9IjY3LjUzMSIgeDI9IjE2NiIgeTI9IjY3LjUzMSIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIxMjMiIHkxPSI2NC41MzEiIHgyPSIxMjMiIHkyPSI2Ni41MzEiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMTY2IiB5MT0iNjQuNTMxIiB4Mj0iMTY2IiB5Mj0iNjYuNTMxIiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PHRleHQgeD0iNyIgeT0iODMuMTMzIiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjEyIiB0ZXh0TGVuZ3RoPSIyOS42ODQiPkxpa2VzPC90ZXh0Pjx0ZXh0IHg9IjEyNSIgeT0iODMuMTMzIiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjEyIj7CoDwvdGV4dD48bGluZSB4MT0iMTIzIiB5MT0iODUuNjY0IiB4Mj0iMTY2IiB5Mj0iODUuNjY0IiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjEyMyIgeTE9IjgyLjY2NCIgeDI9IjEyMyIgeTI9Ijg0LjY2NCIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIxNjYiIHkxPSI4Mi42NjQiIHgyPSIxNjYiIHkyPSI4NC42NjQiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48cmVjdCB4PSI5LjUiIHk9IjkyLjE2NCIgd2lkdGg9IjEwOCIgaGVpZ2h0PSIxOC4xMzMiIGZpbGw9IiNFRUUiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6Mi41OyIgcng9IjUiIHJ5PSI1Ii8+PHRleHQgeD0iMTguNTgyIiB5PSIxMDUuNzY2IiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjEyIiB0ZXh0TGVuZ3RoPSI4OS44MzYiPkFkZCBOZXcvUmVzZXQ8L3RleHQ+PHJlY3QgeD0iMTI0LjUiIHk9IjkyLjE2NCIgd2lkdGg9Ijc2IiBoZWlnaHQ9IjE4LjEzMyIgZmlsbD0iI0VFRSIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoyLjU7IiByeD0iNSIgcnk9IjUiLz48dGV4dCB4PSIxNDkuNTA3IiB5PSIxMDUuNzY2IiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjEyIiB0ZXh0TGVuZ3RoPSIyNS45ODYiPlNhdmU8L3RleHQ+PHJlY3QgeD0iMjA3LjUiIHk9IjkyLjE2NCIgd2lkdGg9IjUyIiBoZWlnaHQ9IjE4LjEzMyIgZmlsbD0iI0VFRSIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoyLjU7IiByeD0iNSIgcnk9IjUiLz48dGV4dCB4PSIyMjAuMzM3IiB5PSIxMDUuNzY2IiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjEyIiB0ZXh0TGVuZ3RoPSIyNi4zMjYiPlN5bmM8L3RleHQ+PGxpbmUgeDE9IjYiIHkxPSIyNy4xOTkiIHgyPSIxMjEiIHkyPSIyNy4xOTkiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMTIxIiB5MT0iMjcuMTk5IiB4Mj0iMjA0IiB5Mj0iMjcuMTk5IiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjIwNCIgeTE9IjI3LjE5OSIgeDI9IjI2MyIgeTI9IjI3LjE5OSIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSI2IiB5MT0iMTEzLjc5NyIgeDI9IjEyMSIgeTI9IjExMy43OTciIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMTIxIiB5MT0iMTEzLjc5NyIgeDI9IjIwNCIgeTI9IjExMy43OTciIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMjA0IiB5MT0iMTEzLjc5NyIgeDI9IjI2MyIgeTI9IjExMy43OTciIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iNiIgeTE9IjI3LjE5OSIgeDI9IjYiIHkyPSI1Mi4zOTgiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMjYzIiB5MT0iODguNjY0IiB4Mj0iMjYzIiB5Mj0iMTEzLjc5NyIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIyNjMiIHkxPSI3MC41MzEiIHgyPSIyNjMiIHkyPSI4OC42NjQiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMjYzIiB5MT0iNTIuMzk4IiB4Mj0iMjYzIiB5Mj0iNzAuNTMxIiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjI2MyIgeTE9IjI3LjE5OSIgeDI9IjI2MyIgeTI9IjUyLjM5OCIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSI2IiB5MT0iODguNjY0IiB4Mj0iNiIgeTI9IjExMy43OTciIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iNiIgeTE9IjcwLjUzMSIgeDI9IjYiIHkyPSI4OC42NjQiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iNiIgeTE9IjUyLjM5OCIgeDI9IjYiIHkyPSI3MC41MzEiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48cmVjdCB4PSIxMiIgeT0iMjAuMTMzIiB3aWR0aD0iNTQuNTI3IiBoZWlnaHQ9IjE0LjEzMyIgZmlsbD0iI0ZGRiIgc3R5bGU9InN0cm9rZTojRkZGO3N0cm9rZS13aWR0aDoxOyIvPjx0ZXh0IHg9IjEyIiB5PSIzMS43MzQiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTIiIHRleHRMZW5ndGg9IjU0LjUyNyI+UG9zdEZvcm08L3RleHQ+PHRleHQgeD0iOCIgeT0iMTU3LjY2NCIgZmlsbD0iIzAwMCIgZm9udC1zaXplPSIxMiIgdGV4dExlbmd0aD0iMjUuNjk5Ij5UaXRsZTwvdGV4dD48dGV4dCB4PSIzNS42OTkiIHk9IjE1Ny42NjQiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTIiIHRleHRMZW5ndGg9IjQ2LjIzIj5Db250ZW50PC90ZXh0Pjx0ZXh0IHg9IjgzLjkzIiB5PSIxNTcuNjY0IiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjEyIiB0ZXh0TGVuZ3RoPSIyOS42ODQiPkxpa2VzPC90ZXh0Pjx0ZXh0IHg9IjExNS42MTMiIHk9IjE1Ny42NjQiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTIiIHRleHRMZW5ndGg9IjYxLjgxNiI+Q3JlYXRlZCBBdDwvdGV4dD48dGV4dCB4PSIxNzkuNDMiIHk9IjE1Ny42NjQiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTIiIHRleHRMZW5ndGg9IjY1LjMzOCI+VXBkYXRlZCBBdDwvdGV4dD48dGV4dCB4PSIyNDYuNzY4IiB5PSIxNTcuNjY0IiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjEyIiB0ZXh0TGVuZ3RoPSI0My4zMTgiPkFjdGlvbnM8L3RleHQ+PHRleHQgeD0iOCIgeT0iMTczLjc5NyIgZmlsbD0iIzAwMCIgZm9udC1zaXplPSIxMiIgdGV4dExlbmd0aD0iNDguODE0Ij5Qb3N0Um93PC90ZXh0PjxyZWN0IHg9IjI0OS4yNjgiIHk9IjE2NC42OTUiIHdpZHRoPSIzNiIgaGVpZ2h0PSIxOC4xMzMiIGZpbGw9IiNFRUUiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6Mi41OyIgcng9IjUiIHJ5PSI1Ii8+PHRleHQgeD0iMjU2LjI2MSIgeT0iMTc4LjI5NyIgZmlsbD0iIzAwMCIgZm9udC1zaXplPSIxMiIgdGV4dExlbmd0aD0iMjIuMDE0Ij5FZGl0PC90ZXh0PjxyZWN0IHg9IjI5Mi4yNjgiIHk9IjE2NC42OTUiIHdpZHRoPSI1MiIgaGVpZ2h0PSIxOC4xMzMiIGZpbGw9IiNFRUUiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6Mi41OyIgcng9IjUiIHJ5PSI1Ii8+PHRleHQgeD0iMjk5Ljc2NyIgeT0iMTc4LjI5NyIgZmlsbD0iIzAwMCIgZm9udC1zaXplPSIxMiIgdGV4dExlbmd0aD0iMzcuMDAyIj5EZWxldGU8L3RleHQ+PGxpbmUgeDE9IjciIHkxPSIxNDUuMDYzIiB4Mj0iMzQuNjk5IiB5Mj0iMTQ1LjA2MyIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSI4Mi45MyIgeTE9IjE4Ni4zMjgiIHgyPSIxMTQuNjEzIiB5Mj0iMTg2LjMyOCIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIzNC42OTkiIHkxPSIxNDUuMDYzIiB4Mj0iODIuOTMiIHkyPSIxNDUuMDYzIiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjExNC42MTMiIHkxPSIxODYuMzI4IiB4Mj0iMTc4LjQzIiB5Mj0iMTg2LjMyOCIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSI4Mi45MyIgeTE9IjE0NS4wNjMiIHgyPSIxMTQuNjEzIiB5Mj0iMTQ1LjA2MyIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIxNzguNDMiIHkxPSIxODYuMzI4IiB4Mj0iMjQ1Ljc2OCIgeTI9IjE4Ni4zMjgiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMTE0LjYxMyIgeTE9IjE0NS4wNjMiIHgyPSIxNzguNDMiIHkyPSIxNDUuMDYzIiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjI0NS43NjgiIHkxPSIxODYuMzI4IiB4Mj0iMjg4Ljc2OCIgeTI9IjE4Ni4zMjgiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMTc4LjQzIiB5MT0iMTQ1LjA2MyIgeDI9IjI0NS43NjgiIHkyPSIxNDUuMDYzIiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjI4OC43NjgiIHkxPSIxODYuMzI4IiB4Mj0iMzQ3Ljc2OCIgeTI9IjE4Ni4zMjgiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMjQ1Ljc2OCIgeTE9IjE0NS4wNjMiIHgyPSIyODguNzY4IiB5Mj0iMTQ1LjA2MyIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIyODguNzY4IiB5MT0iMTQ1LjA2MyIgeDI9IjM0Ny43NjgiIHkyPSIxNDUuMDYzIiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjciIHkxPSIxNjEuMTk1IiB4Mj0iMzQuNjk5IiB5Mj0iMTYxLjE5NSIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIzNC42OTkiIHkxPSIxNjEuMTk1IiB4Mj0iODIuOTMiIHkyPSIxNjEuMTk1IiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjgyLjkzIiB5MT0iMTYxLjE5NSIgeDI9IjExNC42MTMiIHkyPSIxNjEuMTk1IiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjExNC42MTMiIHkxPSIxNjEuMTk1IiB4Mj0iMTc4LjQzIiB5Mj0iMTYxLjE5NSIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIxNzguNDMiIHkxPSIxNjEuMTk1IiB4Mj0iMjQ1Ljc2OCIgeTI9IjE2MS4xOTUiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMjQ1Ljc2OCIgeTE9IjE2MS4xOTUiIHgyPSIyODguNzY4IiB5Mj0iMTYxLjE5NSIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIyODguNzY4IiB5MT0iMTYxLjE5NSIgeDI9IjM0Ny43NjgiIHkyPSIxNjEuMTk1IiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjciIHkxPSIxODYuMzI4IiB4Mj0iMzQuNjk5IiB5Mj0iMTg2LjMyOCIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIzNC42OTkiIHkxPSIxODYuMzI4IiB4Mj0iODIuOTMiIHkyPSIxODYuMzI4IiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjciIHkxPSIxNDUuMDYzIiB4Mj0iNyIgeTI9IjE2MS4xOTUiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMzQuNjk5IiB5MT0iMTQ1LjA2MyIgeDI9IjM0LjY5OSIgeTI9IjE2MS4xOTUiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iODIuOTMiIHkxPSIxNDUuMDYzIiB4Mj0iODIuOTMiIHkyPSIxNjEuMTk1IiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjExNC42MTMiIHkxPSIxNDUuMDYzIiB4Mj0iMTE0LjYxMyIgeTI9IjE2MS4xOTUiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMTc4LjQzIiB5MT0iMTQ1LjA2MyIgeDI9IjE3OC40MyIgeTI9IjE2MS4xOTUiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMjQ1Ljc2OCIgeTE9IjE2MS4xOTUiIHgyPSIyNDUuNzY4IiB5Mj0iMTg2LjMyOCIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIyNDUuNzY4IiB5MT0iMTQ1LjA2MyIgeDI9IjI0NS43NjgiIHkyPSIxNjEuMTk1IiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjI4OC43NjgiIHkxPSIxNjEuMTk1IiB4Mj0iMjg4Ljc2OCIgeTI9IjE4Ni4zMjgiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMzQ3Ljc2OCIgeTE9IjE2MS4xOTUiIHgyPSIzNDcuNzY4IiB5Mj0iMTg2LjMyOCIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSIzNDcuNzY4IiB5MT0iMTQ1LjA2MyIgeDI9IjM0Ny43NjgiIHkyPSIxNjEuMTk1IiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjciIHkxPSIxNjEuMTk1IiB4Mj0iNyIgeTI9IjE4Ni4zMjgiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iNiIgeTE9IjEzNi45OTYiIHgyPSIzNDguNzY4IiB5Mj0iMTM2Ljk5NiIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSI2IiB5MT0iMTg3LjMyOCIgeDI9IjM0OC43NjgiIHkyPSIxODcuMzI4IiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjYiIHkxPSIxMzYuOTk2IiB4Mj0iNiIgeTI9IjE4Ny4zMjgiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMzQ4Ljc2OCIgeTE9IjEzNi45OTYiIHgyPSIzNDguNzY4IiB5Mj0iMTg3LjMyOCIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxyZWN0IHg9IjEyIiB5PSIxMjkuOTMiIHdpZHRoPSI0NS4wODIiIGhlaWdodD0iMTQuMTMzIiBmaWxsPSIjRkZGIiBzdHlsZT0ic3Ryb2tlOiNGRkY7c3Ryb2tlLXdpZHRoOjE7Ii8+PHRleHQgeD0iMTIiIHk9IjE0MS41MzEiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTIiIHRleHRMZW5ndGg9IjQ1LjA4MiI+UG9zdExpc3Q8L3RleHQ+PGxpbmUgeDE9IjUiIHkxPSIxMi4wNjYiIHgyPSIzNDkuNzY4IiB5Mj0iMTIuMDY2IiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjUiIHkxPSIyMDIuNDYxIiB4Mj0iMzQ5Ljc2OCIgeTI9IjIwMi40NjEiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iNSIgeTE9IjEyLjA2NiIgeDI9IjUiIHkyPSIxMjguOTMiIHN0eWxlPSJzdHJva2U6IzAwMDtzdHJva2Utd2lkdGg6MTsiLz48bGluZSB4MT0iMzQ5Ljc2OCIgeTE9IjEyOC45MyIgeDI9IjM0OS43NjgiIHkyPSIyMDIuNDYxIiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjM0OS43NjgiIHkxPSIxMi4wNjYiIHgyPSIzNDkuNzY4IiB5Mj0iMTI4LjkzIiBzdHlsZT0ic3Ryb2tlOiMwMDA7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjUiIHkxPSIxMjguOTMiIHgyPSI1IiB5Mj0iMjAyLjQ2MSIgc3R5bGU9InN0cm9rZTojMDAwO3N0cm9rZS13aWR0aDoxOyIvPjxyZWN0IHg9IjExIiB5PSI1IiB3aWR0aD0iMjMuMzg1IiBoZWlnaHQ9IjE0LjEzMyIgZmlsbD0iI0ZGRiIgc3R5bGU9InN0cm9rZTojRkZGO3N0cm9rZS13aWR0aDoxOyIvPjx0ZXh0IHg9IjExIiB5PSIxNi42MDIiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTIiIHRleHRMZW5ndGg9IjIzLjM4NSI+QXBwPC90ZXh0Pjw/cGxhbnR1bWwtc3JjIFBMM0IyaThtNEJwZEF2UHd5cjBWMXk1Uld1eko0VjVuQVhNQXNLRW05Z0xQNUI3elR4RERLVEdTaVprSnNUYVhZUUVZOWJVSzlDSnA1Q2NnWVdJMHh4Uk1xVGhNTHVPMDFxcWJTakQwbjBLMmxSMjZxRDBsZFVlQmtkenI5Zk0yM1R2N0V0SDhrTl9EMEZSNVpPcTNzWl9DNk44bFJaeVhLa3FlcDN5NzhmWTZEQ3J4VlREbHo0b0QxUTQyb1VJbktYeVdwd0lqT1NzbVNzN2hkUnFwWGQwUWxlUHpYUHgtMWpiQVFILVN3TW85OUhCY3FCY3JOVVBNWTBJRDJoeXZZUVZad0lvVWxtMDA/PjwvZz48L3N2Zz4=\" width=\"355\" height=\"222\" class=\"img_nsRP\"></p>\n<p><code>&lt;App/&gt;</code> consists of:</p>\n<ul>\n<li class=\"\"><code>&lt;PostForm/&gt;</code></li>\n<li class=\"\"><code>&lt;PostList/&gt;</code>\n<ul>\n<li class=\"\"><code>&lt;PostRow/&gt;</code> for each row data</li>\n</ul>\n</li>\n</ul>\n<p>As parent component, <code>App</code> handles all actions related to form (<code>Add New/Reset</code>, <code>Save</code>, <code>Sync</code>) and row data (<code>Edit</code>, <code>Delete</code>).</p>\n<div class=\"language-jsx codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-jsx codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\">// assets/js/blog/App.js</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports maybe-class-name\">React</span><span class=\"token imports punctuation\" style=\"color:#393A34\">,</span><span class=\"token imports\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">{</span><span class=\"token imports\"> useState </span><span class=\"token imports punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'react'</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">{</span><span class=\"token imports\"> useDatabase </span><span class=\"token imports punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'@nozbe/watermelondb/hooks'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">{</span><span class=\"token imports\"> v4 </span><span class=\"token imports keyword module\" style=\"color:#00009f\">as</span><span class=\"token imports\"> uuidv4 </span><span class=\"token imports punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'uuid'</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports\">syncData</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'./sync'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports maybe-class-name\">PostList</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'./PostList'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports maybe-class-name\">PostForm</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'./PostForm'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">export</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">default</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">function</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:#d73a49\">App</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> database </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">useDatabase</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> setPost</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">useState</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> postsCollection </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> database</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">collections</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">get</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"posts\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">clearPost</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:#d73a49\">setPost</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword nil\" style=\"color:#00009f\">undefined</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">onEdit</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter\">selectedPost</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:#d73a49\">setPost</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">selectedPost</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">async</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">onDelete</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter\">selectedPost</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> database</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">action</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">async</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> selectedPost</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">markAsDeleted</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">async</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">createPost</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter\">inputtedForm</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> database</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">action</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">async</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> newPost </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> postsCollection</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">create</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter\">post</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">_raw</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">id</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">uuidv4</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">title</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> inputtedForm</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">title</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">content</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> inputtedForm</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">content</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">likes</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> inputtedForm</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">likes</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">async</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">updatePost</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter\">currentPost</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">,</span><span class=\"token parameter\"> inputtedForm</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> database</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">action</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">async</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> currentPost</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">update</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter\">post</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">title</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> inputtedForm</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">title</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">content</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> inputtedForm</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">content</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">likes</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> inputtedForm</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">likes</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">div</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag class-name\" style=\"color:#00009f\">PostForm</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">post</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">post</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">clearPost</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">clearPost</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">createPost</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">createPost</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">updatePost</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">updatePost</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">syncData</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\"> </span><span class=\"token tag script language-javascript arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\"> </span><span class=\"token tag script language-javascript function\" style=\"color:#d73a49\">syncData</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">database</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag punctuation\" style=\"color:#393A34\">/&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag class-name\" style=\"color:#00009f\">PostList</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onEdit</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">onEdit</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onDelete</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">onDelete</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag punctuation\" style=\"color:#393A34\">/&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">div</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"postformjs\"><code>PostForm.js</code><a href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/#postformjs\" class=\"hash-link\" aria-label=\"Direct link to postformjs\" title=\"Direct link to postformjs\" translate=\"no\">​</a></h3>\n<div class=\"language-jsx codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-jsx codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\">// assets/js/blog/PostForm.js</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports maybe-class-name\">React</span><span class=\"token imports punctuation\" style=\"color:#393A34\">,</span><span class=\"token imports\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">{</span><span class=\"token imports\"> useState</span><span class=\"token imports punctuation\" style=\"color:#393A34\">,</span><span class=\"token imports\"> useEffect </span><span class=\"token imports punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'react'</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">export</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">default</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">function</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:#d73a49\">PostForm</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">{</span><span class=\"token parameter\"> post</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">,</span><span class=\"token parameter\"> clearPost</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">,</span><span class=\"token parameter\"> createPost</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">,</span><span class=\"token parameter\"> updatePost</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">,</span><span class=\"token parameter\"> syncData </span><span class=\"token parameter punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">title</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> setTitle</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">useState</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post </span><span class=\"token operator\" style=\"color:#393A34\">?</span><span class=\"token plain\"> post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">title</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">content</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> setContent</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">useState</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post </span><span class=\"token operator\" style=\"color:#393A34\">?</span><span class=\"token plain\"> post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">content</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">likes</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> setLikes</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">useState</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post </span><span class=\"token operator\" style=\"color:#393A34\">?</span><span class=\"token plain\"> post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">likes</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:#d73a49\">useEffect</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:#d73a49\">setTitle</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post </span><span class=\"token operator\" style=\"color:#393A34\">?</span><span class=\"token plain\"> post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">title</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:#d73a49\">setContent</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post </span><span class=\"token operator\" style=\"color:#393A34\">?</span><span class=\"token plain\"> post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">content</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:#d73a49\">setLikes</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post </span><span class=\"token operator\" style=\"color:#393A34\">?</span><span class=\"token plain\"> post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">likes</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token function-variable function\" style=\"color:#d73a49\">onReset</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        e</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">preventDefault</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:#d73a49\">clearForm</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token function-variable function\" style=\"color:#d73a49\">onSync</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        e</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">preventDefault</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:#d73a49\">syncData</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token function-variable function\" style=\"color:#d73a49\">onSubmit</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">async</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        e</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">preventDefault</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> inputtedForm </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> title</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> content</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">likes</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">parseInt</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">likes</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">updatePost</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> inputtedForm</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">else</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">createPost</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">inputtedForm</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token function\" style=\"color:#d73a49\">clearForm</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token function-variable function\" style=\"color:#d73a49\">clearForm</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:#d73a49\">setTitle</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:#d73a49\">setContent</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:#d73a49\">setLikes</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:#d73a49\">clearPost</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">form</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">label</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">                Title:</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">                </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">input</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">type</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">text</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">value</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">title</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onChange</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag script language-javascript parameter\" style=\"color:#00009f\">e</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\"> </span><span class=\"token tag script language-javascript arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\"> </span><span class=\"token tag script language-javascript function\" style=\"color:#d73a49\">setTitle</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">e</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag script language-javascript property-access\" style=\"color:#00009f\">target</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag script language-javascript property-access\" style=\"color:#00009f\">value</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag punctuation\" style=\"color:#393A34\">/&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">label</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">label</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">                Content:</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">                </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">input</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">type</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">text</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">value</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">content</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onChange</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag script language-javascript parameter\" style=\"color:#00009f\">e</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\"> </span><span class=\"token tag script language-javascript arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\"> </span><span class=\"token tag script language-javascript function\" style=\"color:#d73a49\">setContent</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">e</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag script language-javascript property-access\" style=\"color:#00009f\">target</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag script language-javascript property-access\" style=\"color:#00009f\">value</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag punctuation\" style=\"color:#393A34\">/&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">label</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">label</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">                Likes:</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">                </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">input</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">type</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">number</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">value</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">likes</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onChange</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag script language-javascript parameter\" style=\"color:#00009f\">e</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\"> </span><span class=\"token tag script language-javascript arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\"> </span><span class=\"token tag script language-javascript function\" style=\"color:#d73a49\">setLikes</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">e</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag script language-javascript property-access\" style=\"color:#00009f\">target</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag script language-javascript property-access\" style=\"color:#00009f\">value</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag punctuation\" style=\"color:#393A34\">/&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">label</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">className</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">button button-outline</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onClick</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">onReset</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\">Add New / Reset</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onClick</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">onSubmit</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\">Save</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">className</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:#393A34\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag attr-value\" style=\"color:#e3116c\">button button-clear</span><span class=\"token tag attr-value punctuation\" style=\"color:#393A34\">\"</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onClick</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">onSync</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\">Sync</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">form</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"postlistjs\"><code>PostList.js</code><a href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/#postlistjs\" class=\"hash-link\" aria-label=\"Direct link to postlistjs\" title=\"Direct link to postlistjs\" translate=\"no\">​</a></h3>\n<p><code>PostList</code> is enhanced component wrapped with <code>withObservables</code> to become reactive whenever data in <code>posts</code> get added or deleted.</p>\n<div class=\"language-jsx codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-jsx codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\">// assets/js/blog/PostList.js</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports maybe-class-name\">React</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'react'</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports\">withObservables</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"@nozbe/with-observables\"</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">{</span><span class=\"token imports\"> withDatabase </span><span class=\"token imports punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'@nozbe/watermelondb/DatabaseProvider'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports maybe-class-name\">PostRow</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'./PostRow'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token function-variable function maybe-class-name\" style=\"color:#d73a49\">PostList</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">{</span><span class=\"token parameter\"> posts</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">,</span><span class=\"token parameter\"> onEdit</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">,</span><span class=\"token parameter\"> onDelete </span><span class=\"token parameter punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">table</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">thead</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">tr</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">                </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">th</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\">Title</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">th</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">                </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">th</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\">Content</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">th</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">                </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">th</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\">Likes</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">th</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">                </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">th</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\">Created At</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">th</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">                </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">th</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\">Updated At</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">th</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">                </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">th</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\">Actions</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">th</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">tr</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">thead</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">tbody</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\">posts</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">map</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter\">post</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag class-name\" style=\"color:#00009f\">PostRow</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">key</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">post</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag script language-javascript property-access\" style=\"color:#00009f\">_raw</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag script language-javascript property-access\" style=\"color:#00009f\">id</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">post</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">post</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onEdit</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">onEdit</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onDelete</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">onDelete</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag punctuation\" style=\"color:#393A34\">/&gt;</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">tbody</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">    </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">table</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">export</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">default</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">withDatabase</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token function\" style=\"color:#d73a49\">withObservables</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">{</span><span class=\"token parameter\"> database </span><span class=\"token parameter punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token literal-property property\" style=\"color:#36acaa\">posts</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> database</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">collections</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">get</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">'posts'</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">query</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">observe</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token maybe-class-name\">PostList</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"postrowjs\"><code>PostRow.js</code><a href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/#postrowjs\" class=\"hash-link\" aria-label=\"Direct link to postrowjs\" title=\"Direct link to postrowjs\" translate=\"no\">​</a></h3>\n<p><code>PostRow</code> is also reactive component. It will automatically rerender the component whenever data changes (i.e. <code>post</code> get updated).</p>\n<div class=\"language-jsx codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-jsx codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\">// assets/js/blog/PostRow.js</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports maybe-class-name\">React</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'react'</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports\">withObservables</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"@nozbe/with-observables\"</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token function-variable function maybe-class-name\" style=\"color:#d73a49\">PostRow</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">{</span><span class=\"token parameter\"> post</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">,</span><span class=\"token parameter\"> onEdit</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">,</span><span class=\"token parameter\"> onDelete </span><span class=\"token parameter punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">tr</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">key</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">post</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag script language-javascript property-access\" style=\"color:#00009f\">_raw</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">.</span><span class=\"token tag script language-javascript property-access\" style=\"color:#00009f\">id</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">td</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">title</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">td</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">td</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">content</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">td</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">td</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">likes</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">td</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">td</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">createdAt</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">toString</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">td</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">td</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">updatedAt</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">toString</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">td</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">td</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onClick</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag script language-javascript parameter\" style=\"color:#00009f\">e</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\"> </span><span class=\"token tag script language-javascript arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\"> </span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript function\" style=\"color:#d73a49\">onEdit</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">post</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\">Edit</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">            </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag\" style=\"color:#00009f\"> </span><span class=\"token tag attr-name\" style=\"color:#00a4db\">onClick</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:#393A34\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag script language-javascript parameter\" style=\"color:#00009f\">e</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\"> </span><span class=\"token tag script language-javascript arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\"> </span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">{</span><span class=\"token tag script language-javascript function\" style=\"color:#d73a49\">onDelete</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">(</span><span class=\"token tag script language-javascript\" style=\"color:#00009f\">post</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">)</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag script language-javascript punctuation\" style=\"color:#393A34\">}</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\">Delete</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">button</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">        </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">td</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain-text\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain-text\">    </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">tr</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">export</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">default</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">withObservables</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"post\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">{</span><span class=\"token parameter\"> post </span><span class=\"token parameter punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token literal-property property\" style=\"color:#36acaa\">post</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">observe</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token maybe-class-name\">PostRow</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"syncjs\"><code>sync.js</code><a href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/#syncjs\" class=\"hash-link\" aria-label=\"Direct link to syncjs\" title=\"Direct link to syncjs\" translate=\"no\">​</a></h3>\n<p>Along with the backend, this is the core of sync capability in our app.\nOn <a class=\"\" href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#workaround-for-sync-on-client-side\">the previous post</a>, I have explained in detail why it needs a workaround.\nPlease read that first.</p>\n<div class=\"language-js codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-js codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\">// assets/js/blog/sync.js</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token imports punctuation\" style=\"color:#393A34\">{</span><span class=\"token imports\"> synchronize </span><span class=\"token imports punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'@nozbe/watermelondb/sync'</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:#00009f\">export</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:#00009f\">default</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">async</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">syncData</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter\">database</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">let</span><span class=\"token plain\"> latestVersionOfSession </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">0</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">let</span><span class=\"token plain\"> changesOfSession </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">synchronize</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        database</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function-variable function\" style=\"color:#d73a49\">pullChanges</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">async</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">{</span><span class=\"token parameter\"> lastPulledAt </span><span class=\"token parameter punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> response </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">fetch</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:#e3116c\">`</span><span class=\"token template-string string\" style=\"color:#e3116c\">http://localhost:4000/api/sync/pull?lastPulledVersion=</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:#393A34\">${</span><span class=\"token template-string interpolation\">lastPulledAt </span><span class=\"token template-string interpolation operator\" style=\"color:#393A34\">||</span><span class=\"token template-string interpolation\"> </span><span class=\"token template-string interpolation number\" style=\"color:#36acaa\">0</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:#393A34\">}</span><span class=\"token template-string template-punctuation string\" style=\"color:#e3116c\">`</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token operator\" style=\"color:#393A34\">!</span><span class=\"token plain\">response</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">ok</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">throw</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\">Error</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> response</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">text</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> changes</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> latestVersion </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> response</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">json</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            latestVersionOfSession </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> latestVersion</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            changesOfSession </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> changes</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> changes</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">timestamp</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> latestVersion </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function-variable function\" style=\"color:#d73a49\">pushChanges</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">async</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">{</span><span class=\"token parameter\"> changes</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">,</span><span class=\"token parameter\"> lastPulledAt </span><span class=\"token parameter punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> response </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">fetch</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:#e3116c\">`</span><span class=\"token template-string string\" style=\"color:#e3116c\">http://localhost:4000/api/sync/push?lastPulledVersion=</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:#393A34\">${</span><span class=\"token template-string interpolation\">lastPulledAt </span><span class=\"token template-string interpolation operator\" style=\"color:#393A34\">||</span><span class=\"token template-string interpolation\"> </span><span class=\"token template-string interpolation number\" style=\"color:#36acaa\">0</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:#393A34\">}</span><span class=\"token template-string template-punctuation string\" style=\"color:#e3116c\">`</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token literal-property property\" style=\"color:#36acaa\">method</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'POST'</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token literal-property property\" style=\"color:#36acaa\">headers</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                    </span><span class=\"token string-property property\" style=\"color:#36acaa\">'Content-Type'</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">'application/json'</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token literal-property property\" style=\"color:#36acaa\">body</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token known-class-name class-name\">JSON</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">stringify</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">changes</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token operator\" style=\"color:#393A34\">!</span><span class=\"token plain\">response</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token property-access\">ok</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">throw</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\">Error</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> response</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">text</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword\" style=\"color:#00009f\">const</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">changes</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> changesFromPush</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> latestVersion </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> response</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">json</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            latestVersionOfSession </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> latestVersion</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            changesOfSession </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> changesFromPush</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">synchronize</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        database</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function-variable function\" style=\"color:#d73a49\">pullChanges</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">async</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">{</span><span class=\"token parameter\"> lastPulledAt </span><span class=\"token parameter punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">changes</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> changesOfSession</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token literal-property property\" style=\"color:#36acaa\">timestamp</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> latestVersionOfSession </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token function-variable function\" style=\"color:#d73a49\">pushChanges</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">async</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">{</span><span class=\"token parameter\"> changes</span><span class=\"token parameter punctuation\" style=\"color:#393A34\">,</span><span class=\"token parameter\"> lastPulledAt </span><span class=\"token parameter punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token keyword control-flow\" style=\"color:#00009f\">throw</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\">Error</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword control-flow\" style=\"color:#00009f\">await</span><span class=\"token plain\"> response</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">text</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"run-the-application\">Run the Application<a href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/#run-the-application\" class=\"hash-link\" aria-label=\"Direct link to Run the Application\" title=\"Direct link to Run the Application\" translate=\"no\">​</a></h3>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token builtin class-name\">cd</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">..</span><span class=\"token plain\">/ </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># cd to project directory (blog_app)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix phx.server</span><br></div></code></pre></div></div>\n<p>Open <a href=\"http://localhost:4000/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">http://localhost:4000</a></p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"final-source-code\">Final Source Code<a href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/#final-source-code\" class=\"hash-link\" aria-label=\"Direct link to Final Source Code\" title=\"Direct link to Final Source Code\" translate=\"no\">​</a></h3>\n<p>All code (sync backend and frontend app) is available on <a href=\"https://github.com/fahrinh/blog-labs/tree/master/2020-04-24/blog_app\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://github.com/fahrinh/blog-labs/tree/master/2020-04-24/blog_app</a></p>",
            "url": "https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/",
            "title": "Building an Offline-First React Web App Using WatermelonDB in Phoenix (Elixir)",
            "summary": "Build an offline-first React web application with WatermelonDB and a Phoenix (Elixir) sync backend.",
            "date_modified": "2020-04-29T03:58:39.000Z",
            "author": {
                "name": "Fahri Nurul Hidayat",
                "url": "https://github.com/fahrinh"
            },
            "tags": [
                "React",
                "Phoenix",
                "WatermelonDB",
                "Offline First App"
            ]
        },
        {
            "id": "https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/",
            "content_html": "<h2 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"watermelondb\">WatermelonDB<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#watermelondb\" class=\"hash-link\" aria-label=\"Direct link to WatermelonDB\" title=\"Direct link to WatermelonDB\" translate=\"no\">​</a></h2>\n<p><a href=\"https://github.com/Nozbe/WatermelonDB\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">WatermelonDB</a> is a reactive database for React frontend application that supports data synchronization.</p>\n<p><img decoding=\"async\" loading=\"lazy\" alt=\"WatermelonDB\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGRhdGEtZGlhZ3JhbS10eXBlPSJERVNDUklQVElPTiIgc3R5bGU9IndpZHRoOjQ0NXB4O2hlaWdodDo1MTJweDtiYWNrZ3JvdW5kOiNGRkZGRkY7IiB3aWR0aD0iNDQ1cHgiIGhlaWdodD0iNTEycHgiIHZpZXdCb3g9IjAgMCA0NDUgNTEyIiB6b29tQW5kUGFuPSJtYWduaWZ5IiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyI+PD9wbGFudHVtbCAxLjIwMjYuOT8+PGRlZnMvPjxnIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciPjxnIGNsYXNzPSJ0aXRsZSIgZGF0YS1zb3VyY2UtbGluZT0iMyI+PHRleHQgeD0iMTY2LjUxOSIgeT0iMjMuNTM1IiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjE0IiB0ZXh0TGVuZ3RoPSIxMDUuNTEzIiBmb250LXdlaWdodD0iNzAwIj5XYXRlcm1lbG9uREI8L3RleHQ+PC9nPjwhLS1jbHVzdGVyIEFwcENsaWVudDAxLS0+PGcgY2xhc3M9ImNsdXN0ZXIiIGRhdGEtcXVhbGlmaWVkLW5hbWU9IkFwcENsaWVudDAxIiBpZD0iZW50MDAwMSIgZGF0YS1zb3VyY2UtbGluZT0iNSI+PHJlY3QgeD0iNyIgeT0iNDQuNDg4IiB3aWR0aD0iMTg1LjU1IiBoZWlnaHQ9IjIxNSIgZmlsbD0ibm9uZSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxOyIgcng9IjIuNSIgcnk9IjIuNSIvPjx0ZXh0IHg9IjUwLjQyIiB5PSI2MC4wMjMiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTQiIHRleHRMZW5ndGg9Ijk4LjcxMSIgZm9udC13ZWlnaHQ9IjcwMCI+QXBwIENsaWVudCAwMTwvdGV4dD48L2c+PCEtLWNsdXN0ZXIgV00wMS0tPjxnIGNsYXNzPSJjbHVzdGVyIiBkYXRhLXF1YWxpZmllZC1uYW1lPSJBcHBDbGllbnQwMS5XTTAxIiBpZD0iZW50MDAwMiIgZGF0YS1zb3VyY2UtbGluZT0iNiI+PHJlY3QgeD0iMzkiIHk9Ijk1LjQ4OCIgd2lkdGg9IjEyMS41NSIgaGVpZ2h0PSIxMzIiIGZpbGw9Im5vbmUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MTsiIHJ4PSIyLjUiIHJ5PSIyLjUiLz48dGV4dCB4PSI0Ny4wMTkiIHk9IjExMS4wMjMiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTQiIHRleHRMZW5ndGg9IjEwNS41MTMiIGZvbnQtd2VpZ2h0PSI3MDAiIGZvbnQtc3R5bGU9Iml0YWxpYyI+V2F0ZXJtZWxvbkRCPC90ZXh0PjwvZz48IS0tY2x1c3RlciBBcHBDbGllbnQwMi0tPjxnIGNsYXNzPSJjbHVzdGVyIiBkYXRhLXF1YWxpZmllZC1uYW1lPSJBcHBDbGllbnQwMiIgaWQ9ImVudDAwMDQiIGRhdGEtc291cmNlLWxpbmU9IjExIj48cmVjdCB4PSI3IiB5PSIyODMuNDg4IiB3aWR0aD0iMTg1LjU1IiBoZWlnaHQ9IjIxNSIgZmlsbD0ibm9uZSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxOyIgcng9IjIuNSIgcnk9IjIuNSIvPjx0ZXh0IHg9IjUwLjQyIiB5PSIyOTkuMDIzIiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjE0IiB0ZXh0TGVuZ3RoPSI5OC43MTEiIGZvbnQtd2VpZ2h0PSI3MDAiPkFwcCBDbGllbnQgMDI8L3RleHQ+PC9nPjwhLS1jbHVzdGVyIFdNMDItLT48ZyBjbGFzcz0iY2x1c3RlciIgZGF0YS1xdWFsaWZpZWQtbmFtZT0iQXBwQ2xpZW50MDIuV00wMiIgaWQ9ImVudDAwMDUiIGRhdGEtc291cmNlLWxpbmU9IjEyIj48cmVjdCB4PSIzOSIgeT0iMzM0LjQ4OCIgd2lkdGg9IjEyMS41NSIgaGVpZ2h0PSIxMzIiIGZpbGw9Im5vbmUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MTsiIHJ4PSIyLjUiIHJ5PSIyLjUiLz48dGV4dCB4PSI0Ny4wMTkiIHk9IjM1MC4wMjMiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTQiIHRleHRMZW5ndGg9IjEwNS41MTMiIGZvbnQtd2VpZ2h0PSI3MDAiIGZvbnQtc3R5bGU9Iml0YWxpYyI+V2F0ZXJtZWxvbkRCPC90ZXh0PjwvZz48IS0tY2x1c3RlciBTZXJ2ZXItLT48ZyBjbGFzcz0iY2x1c3RlciIgZGF0YS1xdWFsaWZpZWQtbmFtZT0iU2VydmVyIiBpZD0iZW50MDAwNyIgZGF0YS1zb3VyY2UtbGluZT0iMTciPjxyZWN0IHg9IjI5My41NSIgeT0iMTkyLjQ4OCIgd2lkdGg9IjEzOCIgaGVpZ2h0PSIxMzIiIGZpbGw9Im5vbmUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MTsiIHJ4PSIyLjUiIHJ5PSIyLjUiLz48dGV4dCB4PSIzMDEuMjQyIiB5PSIyMDguMDIzIiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjE0IiB0ZXh0TGVuZ3RoPSIxMjIuNjE2IiBmb250LXdlaWdodD0iNzAwIj5TZXJ2ZXIgLyBCYWNrZW5kPC90ZXh0PjwvZz48IS0tZW50aXR5IExvY2FsREIwMS0tPjxnIGNsYXNzPSJlbnRpdHkiIGRhdGEtcXVhbGlmaWVkLW5hbWU9IkFwcENsaWVudDAxLldNMDEuTG9jYWxEQjAxIiBpZD0iZW50MDAwMyIgZGF0YS1zb3VyY2UtbGluZT0iNyI+PHBhdGggZD0iTTYzLDE2Ny43NDggQzYzLDE1Ny43NDggOTkuNzc2LDE1Ny43NDggOTkuNzc2LDE1Ny43NDggQzk5Ljc3NiwxNTcuNzQ4IDEzNi41NTMsMTU3Ljc0OCAxMzYuNTUzLDE2Ny43NDggTDEzNi41NTMsMTkzLjIzNyBDMTM2LjU1MywyMDMuMjM3IDk5Ljc3NiwyMDMuMjM3IDk5Ljc3NiwyMDMuMjM3IEM5OS43NzYsMjAzLjIzNyA2MywyMDMuMjM3IDYzLDE5My4yMzcgTDYzLDE2Ny43NDgiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgZmlsbD0iI0YxRjFGMSIvPjxwYXRoIGQ9Ik02MywxNjcuNzQ4IEM2MywxNzcuNzQ4IDk5Ljc3NiwxNzcuNzQ4IDk5Ljc3NiwxNzcuNzQ4IEM5OS43NzYsMTc3Ljc0OCAxMzYuNTUzLDE3Ny43NDggMTM2LjU1MywxNjcuNzQ4IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIGZpbGw9Im5vbmUiLz48dGV4dCB4PSI3MyIgeT0iMTk1LjI4MyIgZmlsbD0iIzAwMCIgZm9udC1zaXplPSIxNCIgdGV4dExlbmd0aD0iNTMuNTUzIj5Mb2NhbERCPC90ZXh0PjwvZz48IS0tZW50aXR5IExvY2FsREIwMi0tPjxnIGNsYXNzPSJlbnRpdHkiIGRhdGEtcXVhbGlmaWVkLW5hbWU9IkFwcENsaWVudDAyLldNMDIuTG9jYWxEQjAyIiBpZD0iZW50MDAwNiIgZGF0YS1zb3VyY2UtbGluZT0iMTMiPjxwYXRoIGQ9Ik02Myw0MDYuNzQ4IEM2MywzOTYuNzQ4IDk5Ljc3NiwzOTYuNzQ4IDk5Ljc3NiwzOTYuNzQ4IEM5OS43NzYsMzk2Ljc0OCAxMzYuNTUzLDM5Ni43NDggMTM2LjU1Myw0MDYuNzQ4IEwxMzYuNTUzLDQzMi4yMzcgQzEzNi41NTMsNDQyLjIzNyA5OS43NzYsNDQyLjIzNyA5OS43NzYsNDQyLjIzNyBDOTkuNzc2LDQ0Mi4yMzcgNjMsNDQyLjIzNyA2Myw0MzIuMjM3IEw2Myw0MDYuNzQ4IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIGZpbGw9IiNGMUYxRjEiLz48cGF0aCBkPSJNNjMsNDA2Ljc0OCBDNjMsNDE2Ljc0OCA5OS43NzYsNDE2Ljc0OCA5OS43NzYsNDE2Ljc0OCBDOTkuNzc2LDQxNi43NDggMTM2LjU1Myw0MTYuNzQ4IDEzNi41NTMsNDA2Ljc0OCIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiBmaWxsPSJub25lIi8+PHRleHQgeD0iNzMiIHk9IjQzNC4yODMiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTQiIHRleHRMZW5ndGg9IjUzLjU1MyI+TG9jYWxEQjwvdGV4dD48L2c+PCEtLWVudGl0eSBTZXJ2ZXJEQi0tPjxnIGNsYXNzPSJlbnRpdHkiIGRhdGEtcXVhbGlmaWVkLW5hbWU9IlNlcnZlci5TZXJ2ZXJEQiIgaWQ9ImVudDAwMDgiIGRhdGEtc291cmNlLWxpbmU9IjE4Ij48cGF0aCBkPSJNMzIxLjg2LDI2NC43NDggQzMyMS44NiwyNTQuNzQ4IDM2Mi4wNTEsMjU0Ljc0OCAzNjIuMDUxLDI1NC43NDggQzM2Mi4wNTEsMjU0Ljc0OCA0MDIuMjQyLDI1NC43NDggNDAyLjI0MiwyNjQuNzQ4IEw0MDIuMjQyLDI5MC4yMzcgQzQwMi4yNDIsMzAwLjIzNyAzNjIuMDUxLDMwMC4yMzcgMzYyLjA1MSwzMDAuMjM3IEMzNjIuMDUxLDMwMC4yMzcgMzIxLjg2LDMwMC4yMzcgMzIxLjg2LDI5MC4yMzcgTDMyMS44NiwyNjQuNzQ4IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIGZpbGw9IiNGMUYxRjEiLz48cGF0aCBkPSJNMzIxLjg2LDI2NC43NDggQzMyMS44NiwyNzQuNzQ4IDM2Mi4wNTEsMjc0Ljc0OCAzNjIuMDUxLDI3NC43NDggQzM2Mi4wNTEsMjc0Ljc0OCA0MDIuMjQyLDI3NC43NDggNDAyLjI0MiwyNjQuNzQ4IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIGZpbGw9Im5vbmUiLz48dGV4dCB4PSIzMzEuODYiIHk9IjI5Mi4yODMiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTQiIHRleHRMZW5ndGg9IjYwLjM4MiI+U2VydmVyREI8L3RleHQ+PC9nPjwhLS1saW5rIFdNMDEgdG8gU2VydmVyLS0+PGcgY2xhc3M9ImxpbmsiIGRhdGEtZW50aXR5LTE9ImVudDAwMDIiIGRhdGEtZW50aXR5LTI9ImVudDAwMDciIGlkPSJsbms5IiBkYXRhLXNvdXJjZS1saW5lPSIyMSIgZGF0YS1saW5rLXR5cGU9ImRlcGVuZGVuY3kiPjxwYXRoIGQ9Ik0xNjUuNjYsMTMyLjIzMyBDMTY2LjM0MiwxMzIuMzcyIDE2My4xNDcsMTMxLjczMyAxNjMuODMyLDEzMS44NzYgQzE2NS4yMDEsMTMyLjE2MSAxNjYuNTc2LDEzMi40NTQgMTY3Ljk1MywxMzIuNzU0IEMxNzguOTczLDEzNS4xNTYgMTkwLjE3NSwxMzguMDQ2IDIwMC41NSwxNDEuNDg4IEMyMzcuNiwxNTMuNzc4IDI3Ny4wNiwxNzIuODY2IDMwNy41ODMsMTg5LjA4MiBDMzA5LjQ5LDE5MC4wOTYgMzExLjM2MywxOTEuMDk4IDMxMy4xOTgsMTkyLjA4NyBDMzEzLjQyNywxOTIuMjEgMzA5LjI1NiwxODkuOTU5IDMwOS40ODQsMTkwLjA4MiIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxOyIgZmlsbD0ibm9uZSIgaWQ9IldNMDEtU2VydmVyIi8+PHBvbHlnb24gcG9pbnRzPSIxNjAuNzU4LDEzMS4yNDcsMTY4Ljc5MiwxMzYuOTQ0LDE2NS42NiwxMzIuMjMzLDE3MC4zNzEsMTI5LjEwMSwxNjAuNzU4LDEzMS4yNDciIGZpbGw9IiMxODE4MTgiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MTtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW1pdGVybGltaXQ6MTA7Ii8+PHBvbHlnb24gcG9pbnRzPSIzMTMuODg0LDE5Mi40NTcsMzA3Ljg2NCwxODQuNjYyLDMwOS40ODQsMTkwLjA4MiwzMDQuMDY0LDE5MS43MDIsMzEzLjg4NCwxOTIuNDU3IiBmaWxsPSIjMTgxODE4IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjE7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0OjEwOyIvPjx0ZXh0IHg9IjIwOS41NSIgeT0iMTQxLjE4NyIgZmlsbD0iIzAwMCIgZm9udC1zaXplPSIxMyIgdGV4dExlbmd0aD0iNTkuNjYyIj5zeW5jIGRhdGE8L3RleHQ+PC9nPjwhLS1saW5rIFdNMDIgdG8gU2VydmVyLS0+PGcgY2xhc3M9ImxpbmsiIGRhdGEtZW50aXR5LTE9ImVudDAwMDUiIGRhdGEtZW50aXR5LTI9ImVudDAwMDciIGlkPSJsbmsxMCIgZGF0YS1zb3VyY2UtbGluZT0iMjIiIGRhdGEtbGluay10eXBlPSJkZXBlbmRlbmN5Ij48cGF0aCBkPSJNMTM1LjkzOCwzMzAuODMxIEMxMzYuNzYxLDMzMC4xNDUgMTM0LjM3MywzMzIuMTQyIDEzNS4yMjIsMzMxLjQ0IEMxNDIuMDE0LDMyNS44MjIgMTQ5LjYyOCwzMTkuNjg1IDE1Ny44OTQsMzEzLjI3MSBDMTkwLjk1OCwyODcuNjEzIDIzNC40NTUsMjU3LjUxOCAyNzcuNTUsMjM4LjQ4OCBDMjgxLjc2NiwyMzYuNjI3IDI4Ni4xODYsMjM0LjkzOCAyOTAuNjk4LDIzMy40MDcgQzI5MS4yNjIsMjMzLjIxNSAyOTEuODI3LDIzMy4wMjYgMjkyLjM5NCwyMzIuODQgQzI5Mi42NzcsMjMyLjc0NyAyODguMjA0LDIzNC4xOTYgMjg4LjQ4OCwyMzQuMTA0IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjE7IiBmaWxsPSJub25lIiBpZD0iV00wMi1TZXJ2ZXIiLz48cG9seWdvbiBwb2ludHM9IjEzMi4wOTgsMzM0LjAzNCwxNDEuNTcyLDMzMS4zNCwxMzUuOTM4LDMzMC44MzEsMTM2LjQ0NywzMjUuMTk3LDEzMi4wOTgsMzM0LjAzNCIgZmlsbD0iIzE4MTgxOCIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxO3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2UtbWl0ZXJsaW1pdDoxMDsiLz48cG9seWdvbiBwb2ludHM9IjI5My4yNDQsMjMyLjU2MiwyODMuNDQ5LDIzMS41MzIsMjg4LjQ4OCwyMzQuMTA0LDI4NS45MTcsMjM5LjE0MiwyOTMuMjQ0LDIzMi41NjIiIGZpbGw9IiMxODE4MTgiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MTtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW1pdGVybGltaXQ6MTA7Ii8+PHRleHQgeD0iMjA5LjU1IiB5PSIyMzkuOTA3IiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjEzIiB0ZXh0TGVuZ3RoPSI1OS42NjIiPnN5bmMgZGF0YTwvdGV4dD48L2c+PD9wbGFudHVtbC1zcmMgWlAwbjN1OG00OE50X2VlQkVvYnFEQ1A0VERKOVdSZDJZT3NyOVVMWU9XcF90TDkwWVA2NGN6ZnR4eHJ5RU9xTjBoQldMN0tiQTlOM1dmR3JaOTRZWlAxQkdkVDdSU3EtT3duUkliRHZGVGhNRFVvcUdhRUdmMTc4MWhwSTJxYUFCbVAtOWRSRWZxc1NYcUgtXzVZeEFJTjlpc295LXMwQmdWVFBDMHRsOTBzLWJoTXA2RTg3R29wNzQ4aW5uNS1DNHhlN0VrMkdvVUE2ZldvSEdVb1Jsd3N6RkRJRWR3dWxkNkNUbnZpbmtPQmNRT2VHUEc1b1JsYTY/PjwvZz48L3N2Zz4=\" width=\"445\" height=\"512\" class=\"img_nsRP\"></p>\n<p>What I like about this database is you can bring your own sync backend (HTTP-based) as long as it complies with this spec:</p>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n<table><thead><tr><th>Operation</th><th style=\"text-align:center\">Request Params / Body</th><th style=\"text-align:center\">Response Body</th></tr></thead><tbody><tr><td>Pull</td><td style=\"text-align:center\">- <code>lastPulledAt</code>: <em>integer, Unix time in milliseconds (ms)</em></td><td style=\"text-align:center\">- <code>changes</code>: <em>(JSON)</em> <br> - <code>timestamp</code>: <em>integer, Unix time in milliseconds (ms)</em></td></tr><tr><td>Push</td><td style=\"text-align:center\">- <code>changes</code>: <em>(JSON)</em> <br> - <code>lastPulledAt</code>: <em>integer, Unix time in milliseconds (ms)</em></td><td style=\"text-align:center\"><em>X</em></td></tr></tbody></table>\n<p>The following is a brief how pull and push operation works. Please refer to <a href=\"https://nozbe.github.io/WatermelonDB/Advanced/Sync.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Sync documentation</a> for the details</p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"pull-operation\">Pull Operation<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#pull-operation\" class=\"hash-link\" aria-label=\"Direct link to Pull Operation\" title=\"Direct link to Pull Operation\" translate=\"no\">​</a></h3>\n<p>Request:</p>\n<ul>\n<li class=\"\"><code>lastPulledAt</code> is a timestamp retrieved in the last/previous pull operation</li>\n</ul>\n<p>Response:</p>\n<ul>\n<li class=\"\"><code>changes</code> is a JSON containing changes of data (created, updated, deleted) since <code>lastPulledAt</code> at server</li>\n<li class=\"\"><code>timestamp</code> is a timestamp that will replace <code>lastPulledAt</code> for the next pull operation.</li>\n</ul>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"push-operation\">Push Operation<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#push-operation\" class=\"hash-link\" aria-label=\"Direct link to Push Operation\" title=\"Direct link to Push Operation\" translate=\"no\">​</a></h3>\n<p>Request:</p>\n<ul>\n<li class=\"\"><code>changes</code> is a JSON containing data changes on the client (local) that will be applied by server on server DB.</li>\n<li class=\"\"><code>lastPulledAt</code> is a timestamp retrieved in the last/previous pull operation. This is for conflict detection. Server compare modification time of each row of <code>changes</code> on server DB with <code>lastPulledAt</code>. If it is greater, there is a conflict.</li>\n</ul>\n<p>Response:</p>\n<ul>\n<li class=\"\">No specified response</li>\n</ul>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"changes-example\"><code>changes</code> Example<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#changes-example\" class=\"hash-link\" aria-label=\"Direct link to changes-example\" title=\"Direct link to changes-example\" translate=\"no\">​</a></h3>\n<div class=\"language-json codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-json codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:#36acaa\">\"posts\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token property\" style=\"color:#36acaa\">\"created\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"id\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"d1633195-156f-4f9d-9ccf-7740203b080e\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"_status\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"created\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"_changed\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"title\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Phoenix\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"content\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Phoenix is a web framework for Elixir\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"likes\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">200</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"created_at\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1588400731806</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"updated_at\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1588400731806</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token property\" style=\"color:#36acaa\">\"updated\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"id\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"2d7c6a82-eb04-47b1-be52-6f8f6cf806ff\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"_status\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"updated\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"_changed\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"updated_at,title,content,likes\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"title\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Elixir\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"content\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Elixir is amazing\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"likes\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">100</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"created_at\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1588389279195</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"updated_at\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1588400691047</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token property\" style=\"color:#36acaa\">\"deleted\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token string\" style=\"color:#e3116c\">\"2b130e52-079d-4b31-9f42-ce257cf546f0\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:#36acaa\">\"comments\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token property\" style=\"color:#36acaa\">\"created\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token property\" style=\"color:#36acaa\">\"updated\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"id\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"1e945c88-baf2-4db7-aa39-286b6865b3fb\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">                </span><span class=\"token property\" style=\"color:#36acaa\">\"comment\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"That's good!\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">            </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token property\" style=\"color:#36acaa\">\"deleted\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<ul>\n<li class=\"\"><code>created</code> and <code>updated</code> is an array of object containing created / updated records</li>\n<li class=\"\"><code>deleted</code> is an array of string of deleted IDs</li>\n</ul>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"sync-flow\">Sync Flow<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#sync-flow\" class=\"hash-link\" aria-label=\"Direct link to Sync Flow\" title=\"Direct link to Sync Flow\" translate=\"no\">​</a></h3>\n<p>Based on the documentation and <a href=\"https://nozbe.github.io/WatermelonDB/Advanced/Sync.html#using-synchronize\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">sync code example (<code>synchronize()</code>) on client side</a>, this is what will be expected from sync backend:</p>\n<p><img decoding=\"async\" loading=\"lazy\" alt=\"WatermelonDB Sync Flow\" src=\"https://fahri.blog/assets/images/watermelondb-sync-flow-daa64d341c96216d445fd8b572f6c204.svg\" width=\"609\" height=\"914\" class=\"img_nsRP\"></p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"proposed-alternative-sync-approach\">Proposed Alternative Sync Approach<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#proposed-alternative-sync-approach\" class=\"hash-link\" aria-label=\"Direct link to Proposed Alternative Sync Approach\" title=\"Direct link to Proposed Alternative Sync Approach\" translate=\"no\">​</a></h2>\n<p>While in iterations of prototyping sync backend, I took another approach for tracking changes and made a workaround for an issue in regard to WatermelonDB sync behaviour on client side.</p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"using-auto-incrementing-counter-version--timestamp-for-tracking-changes\">Using Auto-incrementing Counter (Version) + Timestamp for Tracking Changes<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#using-auto-incrementing-counter-version--timestamp-for-tracking-changes\" class=\"hash-link\" aria-label=\"Direct link to Using Auto-incrementing Counter (Version) + Timestamp for Tracking Changes\" title=\"Direct link to Using Auto-incrementing Counter (Version) + Timestamp for Tracking Changes\" translate=\"no\">​</a></h3>\n<p>WatermelonDB sync documentation is good enough to gives a tips for implementing sync backend by using timestamp. It also states:</p>\n<blockquote>\n<p>This protects against weird edge cases related to server clock time changes (NTP time sync, leap seconds, etc.) (<strong>Alternatively, instead of using timestamps, you could use auto-incrementing couters, but you'd have to ensure they are consistent across the whole database, not just one table</strong>)</p>\n</blockquote>\n<p>I followed its suggestion to use auto-incrementing counter. In my approach, for tracking changes, it needs these server DB setup: a global sequence (<code>version_seq</code>) &amp; each table have columns: <code>version</code> (int), <code>version_created</code> (int), <code>created_at_server</code> (timestamp), <code>updated_at_server</code> (timestamp), and <code>deleted_at_server</code> (timestamp).</p>\n<p>Please see <a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#database-design\" class=\"\">Database Design</a> to know how this is implemented in practice.</p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"workaround-for-sync-on-client-side\">Workaround for Sync on Client Side<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#workaround-for-sync-on-client-side\" class=\"hash-link\" aria-label=\"Direct link to Workaround for Sync on Client Side\" title=\"Direct link to Workaround for Sync on Client Side\" translate=\"no\">​</a></h3>\n<p>There is a problem if we use <a href=\"https://nozbe.github.io/WatermelonDB/Advanced/Sync.html#using-synchronize\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">sync code example (<code>synchronize()</code>) for client side on the documentation</a>.</p>\n<p>Please look again at <a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#sync-flow\" class=\"\">Sync Flow diagram</a> above.</p>\n<p>In <strong>8</strong>, after WatermelonDB receives <code>changes</code> &amp; <code>timestamp</code>, internally, <code>timestamp</code> value is set as <code>lastPulledAt</code> for the next pull operation. That is not problem.</p>\n<p>At first, I assume it will have same mechanism for push operation.\nWe got new <code>timestamp</code> that will be become the next <code>lastPulledAt</code>.\nBut I am wrong.\nLook at <strong>15</strong>.\nNo response at all for push operation AND no way to explicitly set <code>lastPulledAt</code> on the push operation.\nIt means for the next pull operation, we will get changes that we've just pushed on previous push operation. Well, it actually mentioned <a href=\"https://nozbe.github.io/WatermelonDB/Advanced/Sync.html#current-limitations\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">in the documentation</a>:</p>\n<blockquote>\n<p>Current limitations</p>\n</blockquote>\n<blockquote>\n<ol start=\"2\">\n<li class=\"\">During next sync pull, changes we've just pushed will be pulled again, which is unnecessary. It would be better if server, during push, also pulled local changes since <code>lastPulledAt</code> and responded with NEW timestamp to be treated as <code>lastPulledAt</code>.</li>\n</ol>\n</blockquote>\n<p>I don't know why this library designed to behave like this. It raised <a href=\"https://github.com/Nozbe/WatermelonDB/issues/649\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">an issue complaining/questioning about that</a>.</p>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"sync-flow-workaround\">Sync Flow Workaround<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#sync-flow-workaround\" class=\"hash-link\" aria-label=\"Direct link to Sync Flow Workaround\" title=\"Direct link to Sync Flow Workaround\" translate=\"no\">​</a></h4>\n<p>So this is what I did for a temporary solution/workaround:</p>\n<p><img decoding=\"async\" loading=\"lazy\" alt=\"WatermelonDB Sync Flow Workaround\" src=\"https://fahri.blog/assets/images/watermelondb-sync-flow-workaround-59bf2a2ddb23ba02491e51357035a6d9.svg\" width=\"720\" height=\"1477\" class=\"img_nsRP\"></p>\n<ul>\n<li class=\"\">introduce variable <code>latestVersionOfSession</code> &amp; <code>changesOfSession</code> (<strong>1</strong>)</li>\n<li class=\"\">call <code>synchronize()</code> twice (<strong>2</strong> &amp; <strong>20</strong>)</li>\n<li class=\"\">on first <code>synchronize()</code>, pull &amp; push operation retrieve <code>latestVersion</code> &amp; <code>changes</code> (<strong>8</strong> &amp; <strong>19</strong>) then set it as <code>latestVersionOfSession</code> &amp; <code>changesOfSession</code> value</li>\n<li class=\"\">on second <code>synchronize()</code>, pull operation only set <code>lastPulledAt = latestVersionOfSession</code> &amp; <code>changes = changesOfSession</code> to be applied on LocalDB (<strong>22</strong>). Push operation does nothing.</li>\n</ul>\n<p>This is workaround for the client side. The code is available on <a class=\"\" href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/\">the next post</a>.</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"application-example-blogapp\">Application Example: BlogApp<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#application-example-blogapp\" class=\"hash-link\" aria-label=\"Direct link to Application Example: BlogApp\" title=\"Direct link to Application Example: BlogApp\" translate=\"no\">​</a></h2>\n<p>Let's say we want to build a blog app (web based) that supports data synchronization.\nUser can submit, edit, and delete a post content. If user click Sync button, data located on current browser will be synced to server. So if user open another browser (another client device), data will be automically synced and available on that browser.</p>\n<p>This tutorial only covers how to build sync backend implementation. Frontend (ReactJS) implementation is available on the next post: <a class=\"\" href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/\">Building an Offline First React Web App Using WatermelonDB in Phoenix (Elixir)</a>.</p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"database-design\">Database Design<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#database-design\" class=\"hash-link\" aria-label=\"Direct link to Database Design\" title=\"Direct link to Database Design\" translate=\"no\">​</a></h3>\n<table><thead>\n  <tr>\n    <th colspan=\"2\">LocalDB</th>\n    <th colspan=\"3\">ServerDB</th>\n  </tr>\n  <tr>\n    <th colspan=\"2\">WatermelonDB<br><code>posts</code> table</th>\n    <th colspan=\"3\">PostgreSQL<br><code>posts</code> table</th>\n  </tr>\n  <tr>\n    <th>Column</th>\n    <th>Type</th>\n    <th>Column</th>\n    <th>Type</th>\n    <th>Default</th>\n  </tr></thead><tbody>\n  <tr>\n    <td><code>id</code></td>\n    <td>string (UUID format)</td>\n    <td><code>id</code></td>\n    <td>uuid (binary)</td>\n    <td>-</td>\n  </tr>\n  <tr>\n    <td><code>title</code></td>\n    <td>string</td>\n    <td><code>title</code></td>\n    <td>varchar</td>\n    <td>-</td>\n  </tr>\n  <tr>\n    <td><code>content</code></td>\n    <td>string</td>\n    <td><code>content</code></td>\n    <td>varchar</td>\n    <td>-</td>\n  </tr>\n  <tr>\n    <td><code>likes</code></td>\n    <td>number</td>\n    <td><code>likes</code></td>\n    <td>integer</td>\n    <td>-</td>\n  </tr>\n  <tr>\n    <td><code>created_at</code></td>\n    <td>number<br>(UNIX timestamp in ms)</td>\n    <td><code>created_at</code></td>\n    <td>timestamp (in μs)</td>\n    <td>-</td>\n  </tr>\n  <tr>\n    <td><code>updated_at</code></td>\n    <td>number<br>(UNIX timestamp in ms)</td>\n    <td><code>updated_at</code></td>\n    <td>timestamp (in μs)</td>\n    <td>-</td>\n  </tr>\n  <tr>\n    <td>-</td>\n    <td>-</td>\n    <td><code>created_at_server</code></td>\n    <td>timestamp (in μs)</td>\n    <td>-</td>\n  </tr>\n  <tr>\n    <td>-</td>\n    <td>-</td>\n    <td><code>updated_at_server</code></td>\n    <td>timestamp (in μs)</td>\n    <td>-</td>\n  </tr>\n  <tr>\n    <td>-</td>\n    <td>-</td>\n    <td><code>deleted_at_server</code></td>\n    <td>timestamp (in μs)</td>\n    <td>-</td>\n  </tr>\n  <tr>\n    <td>-</td>\n    <td>-</td>\n    <td><code>version</code></td>\n    <td>bigint</td>\n    <td><code>nextval('version_seq')</code></td>\n  </tr>\n  <tr>\n    <td>-</td>\n    <td>-</td>\n    <td><code>version_created</code></td>\n    <td>bigint</td>\n    <td><code>nextval('version_seq')</code></td>\n  </tr></tbody></table>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"determining-data-changes\">Determining Data Changes<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#determining-data-changes\" class=\"hash-link\" aria-label=\"Direct link to Determining Data Changes\" title=\"Direct link to Determining Data Changes\" translate=\"no\">​</a></h3>\n<p>For push operation:</p>\n<ul>\n<li class=\"\">when a new data is created:\n<ul>\n<li class=\"\"><code>version = nextval('version_seq')</code></li>\n<li class=\"\"><code>version_created = nextval('version_seq')</code></li>\n<li class=\"\"><code>created_at_server = current time</code></li>\n<li class=\"\"><code>updated_at_server = current time</code></li>\n</ul>\n</li>\n<li class=\"\">when a data is updated:\n<ul>\n<li class=\"\"><code>version = nextval('version_seq')</code></li>\n<li class=\"\"><code>updated_at_server = current time</code></li>\n</ul>\n</li>\n<li class=\"\">when a data is deleted:\n<ul>\n<li class=\"\"><code>version = nextval('version_seq')</code></li>\n<li class=\"\"><code>deleted_at_server = current time</code></li>\n</ul>\n</li>\n</ul>\n<p>For pull operation:</p>\n<ul>\n<li class=\"\">\n<p>retrieve all data that were changed since <code>lastPulledVersion</code>:</p>\n<p><code>SELECT * FROM posts WHERE version_created &gt; &lt;lastPulledVersion&gt; OR version &gt; &lt;lastPulledVersion&gt;</code></p>\n</li>\n<li class=\"\">\n<p>Then categorize which records were created, updated, or deleted :</p>\n<ul>\n<li class=\"\">\n<p>created</p>\n<p><code>version_created &gt; &lt;lastPulledVersion&gt; AND deleted_at_server IS NULL</code></p>\n</li>\n<li class=\"\">\n<p>updated</p>\n<p><code>created_at_server != updated_at_server AND deleted_at_server IS NULL</code></p>\n</li>\n<li class=\"\">\n<p>deleted</p>\n<p><code>deleted_at_server IS NOT NULL</code></p>\n</li>\n</ul>\n</li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"sync-backend-implementation\">Sync Backend Implementation<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#sync-backend-implementation\" class=\"hash-link\" aria-label=\"Direct link to Sync Backend Implementation\" title=\"Direct link to Sync Backend Implementation\" translate=\"no\">​</a></h2>\n<p>Sync Backend consists of four main components: <code>SyncController</code>, <code>Sync</code> context, <code>Blog</code> context, and <code>Repo</code>. If you come from another framework, <em>context</em> is kind of like <em>service</em>.</p>\n<p><img decoding=\"async\" loading=\"lazy\" alt=\"BlogApp Architecture\" src=\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGRhdGEtZGlhZ3JhbS10eXBlPSJERVNDUklQVElPTiIgc3R5bGU9IndpZHRoOjg5OXB4O2hlaWdodDoxMzNweDtiYWNrZ3JvdW5kOiNGRkZGRkY7IiB3aWR0aD0iODk5cHgiIGhlaWdodD0iMTMzcHgiIHZpZXdCb3g9IjAgMCA4OTkgMTMzIiB6b29tQW5kUGFuPSJtYWduaWZ5IiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJub25lIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyI+PD9wbGFudHVtbCAxLjIwMjYuOT8+PGRlZnMvPjxnIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciPjwhLS1jbHVzdGVyIEFQSS0tPjxnIGNsYXNzPSJjbHVzdGVyIiBkYXRhLXF1YWxpZmllZC1uYW1lPSJBUEkiIGlkPSJlbnQwMDAyIiBkYXRhLXNvdXJjZS1saW5lPSI1Ij48cG9seWdvbiBwb2ludHM9IjExMC4wODUsMTYsMTIwLjA4NSw2LDc5MS42ODUsNiw3OTEuNjg1LDk4LDc4MS42ODUsMTA4LDExMC4wODUsMTA4LDExMC4wODUsMTYiIGZpbGw9Im5vbmUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MTtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW1pdGVybGltaXQ6MTA7Ii8+PGxpbmUgeDE9Ijc4MS42ODUiIHkxPSIxNiIgeDI9Ijc5MS42ODUiIHkyPSI2IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjE7Ii8+PGxpbmUgeDE9IjExMC4wODUiIHkxPSIxNiIgeDI9Ijc4MS42ODUiIHkyPSIxNiIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxOyIvPjxsaW5lIHgxPSI3ODEuNjg1IiB5MT0iMTYiIHgyPSI3ODEuNjg1IiB5Mj0iMTA4IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjE7Ii8+PHRleHQgeD0iMzUxLjU3MiIgeT0iMzIuNTM1IiBmaWxsPSIjMDAwIiBmb250LXNpemU9IjE0IiB0ZXh0TGVuZ3RoPSIxOTAuNjI3IiBmb250LXdlaWdodD0iNzAwIj5CbG9nQXBwIFN5bmMgQmFja2VuZCBBUEk8L3RleHQ+PC9nPjwhLS1lbnRpdHkgQ250cmwtLT48ZyBjbGFzcz0iZW50aXR5IiBkYXRhLXF1YWxpZmllZC1uYW1lPSJBUEkuQ250cmwiIGlkPSJlbnQwMDAzIiBkYXRhLXNvdXJjZS1saW5lPSI2Ij48cmVjdCB4PSIxMjYuMDg1IiB5PSI0NS43NiIgd2lkdGg9IjEzOC44NzUiIGhlaWdodD0iNDYuNDg4IiBmaWxsPSIjRjFGMUYxIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIHJ4PSIyLjUiIHJ5PSIyLjUiLz48cmVjdCB4PSIyNDQuOTYiIHk9IjUwLjc2IiB3aWR0aD0iMTUiIGhlaWdodD0iMTAiIGZpbGw9IiNGMUYxRjEiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIvPjxyZWN0IHg9IjI0Mi45NiIgeT0iNTIuNzYiIHdpZHRoPSI0IiBoZWlnaHQ9IjIiIGZpbGw9IiNGMUYxRjEiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIvPjxyZWN0IHg9IjI0Mi45NiIgeT0iNTYuNzYiIHdpZHRoPSI0IiBoZWlnaHQ9IjIiIGZpbGw9IiNGMUYxRjEiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIvPjx0ZXh0IHg9IjE0MS4wODUiIHk9Ijc5LjI5NSIgZmlsbD0iIzAwMCIgZm9udC1zaXplPSIxNCIgdGV4dExlbmd0aD0iOTguODc1Ij5TeW5jQ29udHJvbGxlcjwvdGV4dD48L2c+PCEtLWVudGl0eSBTeW5jLS0+PGcgY2xhc3M9ImVudGl0eSIgZGF0YS1xdWFsaWZpZWQtbmFtZT0iQVBJLlN5bmMiIGlkPSJlbnQwMDA0IiBkYXRhLXNvdXJjZS1saW5lPSI3Ij48cmVjdCB4PSIzMjQuOTU1IiB5PSI0NS43NiIgd2lkdGg9IjEyOC45NzciIGhlaWdodD0iNDYuNDg4IiBmaWxsPSIjRjFGMUYxIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIHJ4PSIyLjUiIHJ5PSIyLjUiLz48cmVjdCB4PSI0MzMuOTMyIiB5PSI1MC43NiIgd2lkdGg9IjE1IiBoZWlnaHQ9IjEwIiBmaWxsPSIjRjFGMUYxIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiLz48cmVjdCB4PSI0MzEuOTMyIiB5PSI1Mi43NiIgd2lkdGg9IjQiIGhlaWdodD0iMiIgZmlsbD0iI0YxRjFGMSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7Ii8+PHJlY3QgeD0iNDMxLjkzMiIgeT0iNTYuNzYiIHdpZHRoPSI0IiBoZWlnaHQ9IjIiIGZpbGw9IiNGMUYxRjEiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIvPjx0ZXh0IHg9IjMzOS45NTUiIHk9Ijc5LjI5NSIgZmlsbD0iIzAwMCIgZm9udC1zaXplPSIxNCIgdGV4dExlbmd0aD0iODguOTc3Ij5TeW5jIENvbnRleHQ8L3RleHQ+PC9nPjwhLS1lbnRpdHkgQmxvZy0tPjxnIGNsYXNzPSJlbnRpdHkiIGRhdGEtcXVhbGlmaWVkLW5hbWU9IkFQSS5CbG9nIiBpZD0iZW50MDAwNSIgZGF0YS1zb3VyY2UtbGluZT0iOCI+PHJlY3QgeD0iNTEzLjkzNSIgeT0iNDUuNzYiIHdpZHRoPSIxMjcuNjkxIiBoZWlnaHQ9IjQ2LjQ4OCIgZmlsbD0iI0YxRjFGMSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiByeD0iMi41IiByeT0iMi41Ii8+PHJlY3QgeD0iNjIxLjYyNiIgeT0iNTAuNzYiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxMCIgZmlsbD0iI0YxRjFGMSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7Ii8+PHJlY3QgeD0iNjE5LjYyNiIgeT0iNTIuNzYiIHdpZHRoPSI0IiBoZWlnaHQ9IjIiIGZpbGw9IiNGMUYxRjEiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIvPjxyZWN0IHg9IjYxOS42MjYiIHk9IjU2Ljc2IiB3aWR0aD0iNCIgaGVpZ2h0PSIyIiBmaWxsPSIjRjFGMUYxIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiLz48dGV4dCB4PSI1MjguOTM1IiB5PSI3OS4yOTUiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTQiIHRleHRMZW5ndGg9Ijg3LjY5MSI+QmxvZyBDb250ZXh0PC90ZXh0PjwvZz48IS0tZW50aXR5IFJlcG8tLT48ZyBjbGFzcz0iZW50aXR5IiBkYXRhLXF1YWxpZmllZC1uYW1lPSJBUEkuUmVwbyIgaWQ9ImVudDAwMDYiIGRhdGEtc291cmNlLWxpbmU9IjkiPjxyZWN0IHg9IjcwMS42MjUiIHk9IjQ1Ljc2IiB3aWR0aD0iNzQuMDYzIiBoZWlnaHQ9IjQ2LjQ4OCIgZmlsbD0iI0YxRjFGMSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiByeD0iMi41IiByeT0iMi41Ii8+PHJlY3QgeD0iNzU1LjY4OSIgeT0iNTAuNzYiIHdpZHRoPSIxNSIgaGVpZ2h0PSIxMCIgZmlsbD0iI0YxRjFGMSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7Ii8+PHJlY3QgeD0iNzUzLjY4OSIgeT0iNTIuNzYiIHdpZHRoPSI0IiBoZWlnaHQ9IjIiIGZpbGw9IiNGMUYxRjEiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIvPjxyZWN0IHg9Ijc1My42ODkiIHk9IjU2Ljc2IiB3aWR0aD0iNCIgaGVpZ2h0PSIyIiBmaWxsPSIjRjFGMUYxIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiLz48dGV4dCB4PSI3MTYuNjI1IiB5PSI3OS4yOTUiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTQiIHRleHRMZW5ndGg9IjM0LjA2MyI+UmVwbzwvdGV4dD48L2c+PCEtLWVudGl0eSBJbnRlcm5ldC0tPjxnIGNsYXNzPSJlbnRpdHkiIGRhdGEtcXVhbGlmaWVkLW5hbWU9IkludGVybmV0IiBpZD0iZW50MDAwMSIgZGF0YS1zb3VyY2UtbGluZT0iMyI+PHBhdGggZD0iTTE5LjQ4LDU1LjY1NiBDMjMuMjcyLDQ0LjQ2MiAzMi4yNjcsNDMuMzU5IDM5LjQ1OSw1Mi4yNzkgQzQ1Ljg4NCw0NC4zMDcgNTUuMzE1LDQzLjM4MiA1OS41NTQsNTQuNTczIEM2OS42ODUsNTMuNDkyIDc0LjU4Miw2MC40ODEgNjguODQ1LDY5LjM2NyBDNzMuMjQ5LDc4LjcwOCA2OS42NTUsODMuMzMzIDYwLjEwOSw4NC43NTQgQzU1LjI4OSw5Ni4wMTMgNDcuNDk5LDk4LjYwOCAzOC4xODMsODkuNjI0IEMzMS43MjMsOTguMDg5IDIyLjIwNiw5NS43MDcgMTguNzQ3LDg2LjM1MiBDOC45LDg0LjUxIDYsNzguMjY3IDEwLjk4OCw2OS41NjcgQzcuMTM4LDYxLjE2IDEwLjAwOSw1NS45MzEgMTkuNDgsNTUuNjU2IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIGZpbGw9IiNGMUYxRjEiLz48dGV4dCB4PSIyNC41MjUiIHk9Ijc0LjI5NSIgZmlsbD0iIzAwMCIgZm9udC1zaXplPSIxNCIgdGV4dExlbmd0aD0iMjYuNTU4Ij5+fn48L3RleHQ+PC9nPjwhLS1lbnRpdHkgREItLT48ZyBjbGFzcz0iZW50aXR5IiBkYXRhLXF1YWxpZmllZC1uYW1lPSJEQiIgaWQ9ImVudDAwMDciIGRhdGEtc291cmNlLWxpbmU9IjEyIj48cGF0aCBkPSJNODM1LjY4NSw1Ni4yNiBDODM1LjY4NSw0Ni4yNiA4NTQuOTU1LDQ2LjI2IDg1NC45NTUsNDYuMjYgQzg1NC45NTUsNDYuMjYgODc0LjIyNCw0Ni4yNiA4NzQuMjI0LDU2LjI2IEw4NzQuMjI0LDgxLjc0OCBDODc0LjIyNCw5MS43NDggODU0Ljk1NSw5MS43NDggODU0Ljk1NSw5MS43NDggQzg1NC45NTUsOTEuNzQ4IDgzNS42ODUsOTEuNzQ4IDgzNS42ODUsODEuNzQ4IEw4MzUuNjg1LDU2LjI2IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIGZpbGw9IiNGMUYxRjEiLz48cGF0aCBkPSJNODM1LjY4NSw1Ni4yNiBDODM1LjY4NSw2Ni4yNiA4NTQuOTU1LDY2LjI2IDg1NC45NTUsNjYuMjYgQzg1NC45NTUsNjYuMjYgODc0LjIyNCw2Ni4yNiA4NzQuMjI0LDU2LjI2IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIGZpbGw9Im5vbmUiLz48dGV4dCB4PSI4NDUuNjg1IiB5PSI4My43OTUiIGZpbGw9IiMwMDAiIGZvbnQtc2l6ZT0iMTQiIHRleHRMZW5ndGg9IjE4LjUzOSI+REI8L3RleHQ+PC9nPjwhLS1saW5rIEludGVybmV0IHRvIENudHJsLS0+PGcgY2xhc3M9ImxpbmsiIGRhdGEtZW50aXR5LTE9ImVudDAwMDEiIGRhdGEtZW50aXR5LTI9ImVudDAwMDMiIGlkPSJsbms4IiBkYXRhLXNvdXJjZS1saW5lPSIxNCIgZGF0YS1saW5rLXR5cGU9ImRlcGVuZGVuY3kiPjxwYXRoIGQ9Ik02Ni4yODUsNjkgQzgyLjg3NSw2OSA5OS44MDUsNjkgMTIwLjgzNSw2OSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxOyIgZmlsbD0ibm9uZSIgaWQ9IkludGVybmV0LXRvLUNudHJsIi8+PHBvbHlnb24gcG9pbnRzPSIxMjUuODM1LDY5LDExNi44MzUsNjUsMTIwLjgzNSw2OSwxMTYuODM1LDczLDEyNS44MzUsNjkiIGZpbGw9IiMxODE4MTgiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MTtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW1pdGVybGltaXQ6MTA7Ii8+PC9nPjwhLS1saW5rIENudHJsIHRvIFN5bmMtLT48ZyBjbGFzcz0ibGluayIgZGF0YS1lbnRpdHktMT0iZW50MDAwMyIgZGF0YS1lbnRpdHktMj0iZW50MDAwNCIgaWQ9ImxuazkiIGRhdGEtc291cmNlLWxpbmU9IjE1IiBkYXRhLWxpbmstdHlwZT0iZGVwZW5kZW5jeSI+PHBhdGggZD0iTTI2NS4yNjUsNjkgQzI4NC42MjUsNjkgMzAwLjYwNSw2OSAzMTkuNjU1LDY5IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjE7IiBmaWxsPSJub25lIiBpZD0iQ250cmwtdG8tU3luYyIvPjxwb2x5Z29uIHBvaW50cz0iMzI0LjY1NSw2OSwzMTUuNjU1LDY1LDMxOS42NTUsNjksMzE1LjY1NSw3MywzMjQuNjU1LDY5IiBmaWxsPSIjMTgxODE4IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjE7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0OjEwOyIvPjwvZz48IS0tbGluayBTeW5jIHRvIEJsb2ctLT48ZyBjbGFzcz0ibGluayIgZGF0YS1lbnRpdHktMT0iZW50MDAwNCIgZGF0YS1lbnRpdHktMj0iZW50MDAwNSIgaWQ9ImxuazEwIiBkYXRhLXNvdXJjZS1saW5lPSIxNiIgZGF0YS1saW5rLXR5cGU9ImRlcGVuZGVuY3kiPjxwYXRoIGQ9Ik00NTQuMzE1LDY5IEM0NzMuNDg1LDY5IDQ4OS41MDUsNjkgNTA4LjYyNSw2OSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxOyIgZmlsbD0ibm9uZSIgaWQ9IlN5bmMtdG8tQmxvZyIvPjxwb2x5Z29uIHBvaW50cz0iNTEzLjYyNSw2OSw1MDQuNjI1LDY1LDUwOC42MjUsNjksNTA0LjYyNSw3Myw1MTMuNjI1LDY5IiBmaWxsPSIjMTgxODE4IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjE7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0OjEwOyIvPjwvZz48IS0tbGluayBCbG9nIHRvIFJlcG8tLT48ZyBjbGFzcz0ibGluayIgZGF0YS1lbnRpdHktMT0iZW50MDAwNSIgZGF0YS1lbnRpdHktMj0iZW50MDAwNiIgaWQ9ImxuazExIiBkYXRhLXNvdXJjZS1saW5lPSIxNyIgZGF0YS1saW5rLXR5cGU9ImRlcGVuZGVuY3kiPjxwYXRoIGQ9Ik02NDIuMDI1LDY5IEM2NjIuMTA1LDY5IDY3OC42MjUsNjkgNjk2LjE1NSw2OSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxOyIgZmlsbD0ibm9uZSIgaWQ9IkJsb2ctdG8tUmVwbyIvPjxwb2x5Z29uIHBvaW50cz0iNzAxLjE1NSw2OSw2OTIuMTU1LDY1LDY5Ni4xNTUsNjksNjkyLjE1NSw3Myw3MDEuMTU1LDY5IiBmaWxsPSIjMTgxODE4IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjE7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0OjEwOyIvPjwvZz48IS0tbGluayBSZXBvIHRvIERCLS0+PGcgY2xhc3M9ImxpbmsiIGRhdGEtZW50aXR5LTE9ImVudDAwMDYiIGRhdGEtZW50aXR5LTI9ImVudDAwMDciIGlkPSJsbmsxMiIgZGF0YS1zb3VyY2UtbGluZT0iMTgiIGRhdGEtbGluay10eXBlPSJkZXBlbmRlbmN5Ij48cGF0aCBkPSJNNzc2LjEzNSw2OSBDNzk1Ljg2NSw2OSA4MTQuMzk1LDY5IDgzMC4zODUsNjkiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MTsiIGZpbGw9Im5vbmUiIGlkPSJSZXBvLXRvLURCIi8+PHBvbHlnb24gcG9pbnRzPSI4MzUuMzg1LDY5LDgyNi4zODUsNjUsODMwLjM4NSw2OSw4MjYuMzg1LDczLDgzNS4zODUsNjkiIGZpbGw9IiMxODE4MTgiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MTtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW1pdGVybGltaXQ6MTA7Ii8+PC9nPjw/cGxhbnR1bWwtc3JjIExPd24zaThtMzRIdFZ1TkxsUi0wcjlRYjZ1OEhDT0o0RzRLS0x3Y0hHOFgtRXg0QkdjSG1TbFVpa3FHdzJHZlo3aXVObUoxYXlaOW0wbDJIUm02aFVQdWhUMUZzSUlXZDRlMzRXUjFnOHYtUlNTSlQ4dGJpZFJ6STJqWGlVYmlrRHB1MW96YWh4cFg5dlhXZjd2SHNIU0tWSFNMcTVzRGdCNFdCX2YwUTJ6aElvNlJmMHJ1MG1PYXhrZWJtdEdCMnp3ak9yd2pGY0t0SkxjMnJnWXBKY2JIUGQwdko5VWlEPz48L2c+PC9zdmc+\" width=\"899\" height=\"133\" class=\"img_nsRP\"></p>\n<p>We will build sync backend using Elixir 1.10 and Phoenix 1.5.1</p>\n<p>Install Phoenix 1.5.1:</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix archive.uninstall phx_new</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix archive.install hex phx_new </span><span class=\"token number\" style=\"color:#36acaa\">1.5</span><span class=\"token plain\">.1</span><br></div></code></pre></div></div>\n<p>Generate a new Phoenix web app:</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix phx.new blog_app</span><br></div></code></pre></div></div>\n<p>We will use PostgreSQL on Docker with password and database name specified on <code>config/dev.exs</code>:</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">docker</span><span class=\"token plain\"> run </span><span class=\"token parameter variable\" style=\"color:#36acaa\">--name</span><span class=\"token plain\"> blog-db </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-e</span><span class=\"token plain\"> </span><span class=\"token assign-left variable\" style=\"color:#36acaa\">POSTGRES_PASSWORD</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\">postgres </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-e</span><span class=\"token plain\"> </span><span class=\"token assign-left variable\" style=\"color:#36acaa\">POSTGRES_DB</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\">blog_app_dev </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-d</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-p</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">5432</span><span class=\"token plain\">:5432 postgres:12.2</span><br></div></code></pre></div></div>\n<p>Create the database:</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token builtin class-name\">cd</span><span class=\"token plain\"> blog_app</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix ecto.create</span><br></div></code></pre></div></div>\n<p>Create <code>version_seq</code> sequence that will generate version for each data changes :</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix ecto.gen.migration create_version_seq</span><br></div></code></pre></div></div>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># priv/repo/migrations/xxx_create_version_seq.exs</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogApp</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Repo</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Migrations</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">CreateVersionSeq</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">use</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Ecto</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Migration</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> change </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    execute </span><span class=\"token string\" style=\"color:#e3116c\">\"CREATE SEQUENCE version_seq\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix ecto.migrate</span><br></div></code></pre></div></div>\n<p>Generate <code>Post</code> schema:</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix phx.gen.schema Blog.Post posts title:string content:string likes:integer push_id:integer created_at:utc_datetime_usec updated_at:utc_datetime_usec created_at_server:utc_datetime_usec updated_at_server:utc_datetime_usec deleted_at_server:utc_datetime_usec version:integer version_created:integer --binary-id</span><br></div></code></pre></div></div>\n<p>Set default value of <code>version*</code> columns with a incremental number generated by <code>version_seq</code>.\nAs it may increase overtime, change <code>version*</code> columns type to <code>bigint</code> to support bigger value.\nWe don't need <code>inserted_at</code> and <code>updated_at</code> columns generated by Phoenix so we omit <code>timestamps()</code>.\nEdit <code>xxx_create_posts.exs</code>:</p>\n<div class=\"language-diff codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-diff codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"># priv/repo/migrations/xxx_create_posts.exs</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">defmodule BlogApp.Repo.Migrations.CreatePosts do</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\"> use Ecto.Migration</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\"> def change do</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   create table(:posts, primary_key: false) do</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">     add :id, :binary_id, primary_key: true</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">     add :title, :string</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">     add :content, :string</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">     add :likes, :integer</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">     add :created_at, :utc_datetime_usec</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">     add :updated_at, :utc_datetime_usec</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">     add :created_at_server, :utc_datetime_usec</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">     add :updated_at_server, :utc_datetime_usec</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">     add :deleted_at_server, :utc_datetime_usec</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">     add :push_id, :integer</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token deleted-sign deleted prefix deleted\" style=\"color:#d73a49\">-</span><span class=\"token deleted-sign deleted line\" style=\"color:#d73a49\">     add :version, :integer</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token deleted-sign deleted line\" style=\"color:#d73a49\"></span><span class=\"token inserted-sign inserted prefix inserted\" style=\"color:#36acaa\">+</span><span class=\"token inserted-sign inserted line\" style=\"color:#36acaa\">     add :version, :bigint, default: fragment(\"nextval('version_seq')\")</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token inserted-sign inserted line\" style=\"color:#36acaa\"></span><span class=\"token deleted-sign deleted prefix deleted\" style=\"color:#d73a49\">-</span><span class=\"token deleted-sign deleted line\" style=\"color:#d73a49\">     add :version_created, :integer</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token deleted-sign deleted line\" style=\"color:#d73a49\"></span><span class=\"token inserted-sign inserted prefix inserted\" style=\"color:#36acaa\">+</span><span class=\"token inserted-sign inserted line\" style=\"color:#36acaa\">     add :version_created, :bigint, default: fragment(\"nextval('version_seq')\")</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token inserted-sign inserted line\" style=\"color:#36acaa\"></span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token deleted-sign deleted prefix deleted\" style=\"color:#d73a49\">-</span><span class=\"token deleted-sign deleted line\" style=\"color:#d73a49\">     timestamps()</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token deleted-sign deleted line\" style=\"color:#d73a49\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   end</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\"> end</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token plain\">end</span><br></div></code></pre></div></div>\n<p>To enable JSON encoding for <code>Post</code> schema, annotate it with <code>@derive</code> <code>Jason.Encoder</code> for certain columns only:</p>\n<div class=\"language-diff codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-diff codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"># lib/blog_app/blog/post.ex</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">defmodule BlogApp.Blog.Post do</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\"> use Ecto.Schema</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\"> import Ecto.Changeset</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\"> @primary_key {:id, :binary_id, autogenerate: true}</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\"> @foreign_key_type :binary_id</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token inserted-sign inserted prefix inserted\" style=\"color:#36acaa\">+</span><span class=\"token inserted-sign inserted line\" style=\"color:#36acaa\"> @derive {Jason.Encoder, only: [:id, :title, :content, :likes]}</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token inserted-sign inserted line\" style=\"color:#36acaa\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\"> schema \"posts\" do</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   field :title, :string</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   field :content, :string</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   field :likes, :integer</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   field :created_at, :utc_datetime_usec</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   field :updated_at, :utc_datetime_usec</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   field :created_at_server, :utc_datetime_usec</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   field :updated_at_server, :utc_datetime_usec</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   field :deleted_at_server, :utc_datetime_usec</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   field :push_id, :integer</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   field :version, :integer</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\">   field :version_created, :integer</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token deleted-sign deleted prefix deleted\" style=\"color:#d73a49\">-</span><span class=\"token deleted-sign deleted line\" style=\"color:#d73a49\">   timestamps()</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token deleted-sign deleted line\" style=\"color:#d73a49\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\"> end</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token unchanged prefix unchanged\"> </span><span class=\"token unchanged line\"> # ...</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token unchanged line\"></span><span class=\"token plain\">end</span><br></div></code></pre></div></div>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix ecto.migrate</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"sync-endpoint\">Sync Endpoint<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#sync-endpoint\" class=\"hash-link\" aria-label=\"Direct link to Sync Endpoint\" title=\"Direct link to Sync Endpoint\" translate=\"no\">​</a></h3>\n<p>Sync endpoint will be handled by:</p>\n<ul>\n<li class=\"\">push: <code>POST /api/sync/push?lastPulledVersion=&lt;lastPulledVersion&gt;</code></li>\n<li class=\"\">pull: <code>GET /api/sync/pull?lastPulledVersion=&lt;lastPulledVersion&gt;</code></li>\n</ul>\n<p>Edit <code>lib/blog_app_web/router.ex</code></p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># lib/blog_app_web/router.ex</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogAppWeb</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Router</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    scope </span><span class=\"token string\" style=\"color:#e3116c\">\"/api\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogAppWeb</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      pipe_through </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:api</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      post </span><span class=\"token string\" style=\"color:#e3116c\">\"/sync/push\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token module class-name\">SyncController</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:push</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      get </span><span class=\"token string\" style=\"color:#e3116c\">\"/sync/pull\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token module class-name\">SyncController</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:pull</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"controller\">Controller<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#controller\" class=\"hash-link\" aria-label=\"Direct link to Controller\" title=\"Direct link to Controller\" translate=\"no\">​</a></h4>\n<p>Create <code>lib/blog_app_web/controllers/sync_controller.ex</code></p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># lib/blog_app_web/controllers/sync_controller.ex</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogAppWeb</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">SyncController</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">use</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogAppWeb</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:controller</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">alias</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogApp</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Sync</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">push</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token module class-name\">Plug</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Conn</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">          </span><span class=\"token attr-name\" style=\"color:#00a4db\">body_params:</span><span class=\"token plain\"> req_body</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">          </span><span class=\"token attr-name\" style=\"color:#00a4db\">query_params:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token string\" style=\"color:#e3116c\">\"lastPulledVersion\"</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> conn</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        _params</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    resp </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\">  </span><span class=\"token module class-name\">Sync</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">push</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">req_body</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token module class-name\">String</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">to_integer</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:#d73a49\">json</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">conn</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> resp</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">pull</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token module class-name\">Plug</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Conn</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">          </span><span class=\"token attr-name\" style=\"color:#00a4db\">query_params:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token string\" style=\"color:#e3116c\">\"lastPulledVersion\"</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> conn</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        _params</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    resp </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Sync</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">pull</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token module class-name\">String</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">to_integer</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:#d73a49\">json</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">conn</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> resp</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"push\">Push<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#push\" class=\"hash-link\" aria-label=\"Direct link to Push\" title=\"Direct link to Push\" translate=\"no\">​</a></h3>\n<p>Changes have to be recorded in a DB transaction.\nIf there is a failed data operation, every operation must be rolled back.</p>\n<p>In a push operation, data that will be recorded are also annotated with a <code>push_id</code>.\nLater on, after push operation has been successfully applied, all changes since <code>last_pulled_version</code> are retrieved to become push response except those have already been applied (filtered with <code>push_id</code>).</p>\n<p><code>BlogApp.Sync.push/2</code>:</p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># lib/blog_app/sync.ex</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogApp</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Sync</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">alias</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogApp</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token module class-name\">Repo</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Blog</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">push</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">changes</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    push_id </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">random</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token number\" style=\"color:#36acaa\">1</span><span class=\"token operator\" style=\"color:#393A34\">..</span><span class=\"token number\" style=\"color:#36acaa\">1_000_000_000</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token module class-name\">Ecto</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Multi</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">new</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Blog</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">record_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">changes</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"posts\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Repo</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">transaction</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:#d73a49\">pull</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<p><code>BlogApp.Blog.record_posts/4</code>:</p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># lib/blog_app/blog.ex</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogApp</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Blog</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Ecto</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Query</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">alias</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Ecto</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Multi</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">alias</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogApp</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Repo</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">alias</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogApp</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Blog</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Post</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">record_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token module class-name\">Multi</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> multi</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> post_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    multi</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Multi</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">run</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:check_conflict_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> _</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> _changes </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token keyword\" style=\"color:#00009f\">case</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">check_conflict_version_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:no_conflict</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:ok</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:no_conflict</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:conflict</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:error</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:conflict</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">record_created_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"created\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">set_push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">record_updated_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"updated\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">set_push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">record_deleted_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"deleted\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">defp</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">set_push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">posts</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    posts</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">map</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> post </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> post </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Map</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">put</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"push_id\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"conflict-detection\">Conflict Detection<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#conflict-detection\" class=\"hash-link\" aria-label=\"Direct link to Conflict Detection\" title=\"Direct link to Conflict Detection\" translate=\"no\">​</a></h4>\n<p>Conflict happens when other users/clients have modified data that we're pushing.</p>\n<p><code>Blog.check_conflict_version_posts/2</code> :</p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># lib/blog_app/blog.ex</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogApp</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Blog</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">check_conflict_version_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    ids </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">concat</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"created\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> post_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"updated\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">map</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> post </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> post</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"id\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">concat</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"deleted\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    count </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token module class-name\">Post</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">select</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">p</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">count</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">p</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">version</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">where</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">p</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> p</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">id </span><span class=\"token operator\" style=\"color:#393A34\">in</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">^</span><span class=\"token plain\">ids</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">where</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">p</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> p</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">version </span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">^</span><span class=\"token plain\">last_pulled_version </span><span class=\"token keyword\" style=\"color:#00009f\">or</span><span class=\"token plain\"> p</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">version_created </span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">^</span><span class=\"token plain\">last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Repo</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">one</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">case</span><span class=\"token plain\"> count </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token number\" style=\"color:#36acaa\">0</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:no_conflict</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      _ </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:conflict</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"storing-record-changes\">Storing Record Changes<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#storing-record-changes\" class=\"hash-link\" aria-label=\"Direct link to Storing Record Changes\" title=\"Direct link to Storing Record Changes\" translate=\"no\">​</a></h4>\n<p>Data changes are saved on database in bulk using <code>INSERT INTO CONFLICT</code> on PostgreSQL.\nThis is also known as UPSERT (update or insert).</p>\n<p><code>Blog.upsert_posts/3</code> handle both create &amp; update case.\n<code>Blog.record_created_posts/2</code> &amp; <code>Blog.record_updated_posts/2</code> :</p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># lib/blog_app/blog.ex</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogApp</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Blog</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">record_created_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token module class-name\">Multi</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> multi</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> created_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token attr-name\" style=\"color:#00a4db\">do:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">upsert_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">multi</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:create_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> created_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">record_updated_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token module class-name\">Multi</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> multi</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> updated_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token attr-name\" style=\"color:#00a4db\">do:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">upsert_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">multi</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:update_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> updated_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">upsert_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token module class-name\">Multi</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> multi</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> _name</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> changes</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">when</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">is_nil</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">changes</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token attr-name\" style=\"color:#00a4db\">do:</span><span class=\"token plain\"> multi</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">upsert_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token module class-name\">Multi</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> multi</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> name</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> changes</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    now </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token module class-name\">DateTime</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">utc_now</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    posts </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      changes</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">map</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> row </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        row</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Map</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">put</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"created_at\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> row</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"created_at\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">*</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1000</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">DateTime</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">from_unix!</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:microsecond</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Map</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">put</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"updated_at\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> row</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"updated_at\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">*</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1000</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">DateTime</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">from_unix!</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:microsecond</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Map</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">put</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"created_at_server\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> now</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Map</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">put</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"updated_at_server\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> now</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Map</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">take</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token string\" style=\"color:#e3116c\">\"id\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"title\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"content\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"likes\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"created_at\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"updated_at\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"created_at_server\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"updated_at_server\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"push_id\"</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">key_to_atom</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token module class-name\">Multi</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">insert_all</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">multi</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> name</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Post</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> posts</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token attr-name\" style=\"color:#00a4db\">conflict_target:</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:id</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token attr-name\" style=\"color:#00a4db\">on_conflict:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:replace_all_except</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:id</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:version_created</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:created_at_server</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:deleted_at_server</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token attr-name\" style=\"color:#00a4db\">returning:</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">key_to_atom</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">map</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">reduce</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">map</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\">key</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> value</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> acc </span><span class=\"token keyword\" style=\"color:#00009f\">when</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">is_atom</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">key</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Map</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">put</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">acc</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> key</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> value</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\">key</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> value</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> acc </span><span class=\"token keyword\" style=\"color:#00009f\">when</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">is_binary</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">key</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Map</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">put</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">acc</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token module class-name\">String</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">to_existing_atom</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">key</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> value</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<p><code>Blog.record_deleted_posts/3</code> :</p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># lib/blog_app/blog.ex</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogApp</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Blog</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">record_deleted_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token module class-name\">Multi</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> multi</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> deleted_ids</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> _push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">when</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">is_nil</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">deleted_ids</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token attr-name\" style=\"color:#00a4db\">do:</span><span class=\"token plain\"> multi</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">record_deleted_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token module class-name\">Multi</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> multi</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> deleted_ids</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    now </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token module class-name\">DateTime</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">utc_now</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    posts </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      deleted_ids</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">map</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> id </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token attr-name\" style=\"color:#00a4db\">id:</span><span class=\"token plain\"> id</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token attr-name\" style=\"color:#00a4db\">deleted_at_server:</span><span class=\"token plain\"> now</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token attr-name\" style=\"color:#00a4db\">push_id:</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token module class-name\">Multi</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">insert_all</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">multi</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:delete_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Post</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> posts</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token attr-name\" style=\"color:#00a4db\">conflict_target:</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:id</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token attr-name\" style=\"color:#00a4db\">on_conflict:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:replace</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:deleted_at_server</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:version</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token attr-name\" style=\"color:#00a4db\">returning:</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"pull\">Pull<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#pull\" class=\"hash-link\" aria-label=\"Direct link to Pull\" title=\"Direct link to Pull\" translate=\"no\">​</a></h3>\n<p>Pull endpoint calls <code>Sync.pull</code> without <code>push_id</code> specified.\nIt means all data changes since <code>last_pulled_version</code> become the response of pull operation.</p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># lib/blog_app/sync.ex</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogApp</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Sync</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">pull</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id </span><span class=\"token operator\" style=\"color:#393A34\">\\\\</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">nil</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token attr-name\" style=\"color:#00a4db\">latest_version:</span><span class=\"token plain\"> latest_version_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token attr-name\" style=\"color:#00a4db\">changes:</span><span class=\"token plain\"> posts_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token module class-name\">Blog</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">list_posts_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    latest_version </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> latest_version_posts</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">max</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token string\" style=\"color:#e3116c\">\"latestVersion\"</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> latest_version</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token string\" style=\"color:#e3116c\">\"changes\"</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token string\" style=\"color:#e3116c\">\"posts\"</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=&gt;</span><span class=\"token plain\"> posts_changes</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<p><code>Blog.list_posts_changes/2</code>:</p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># lib/blog_app/blog.ex</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">BlogApp</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Blog</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">list_posts_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    posts_latest </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token module class-name\">Post</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">where</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">p</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> p</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">version_created </span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">^</span><span class=\"token plain\">last_pulled_version </span><span class=\"token keyword\" style=\"color:#00009f\">or</span><span class=\"token plain\"> p</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">version </span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">^</span><span class=\"token plain\">last_pulled_version</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Repo</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">all</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    posts_changes </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      posts_latest</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">reject</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> post </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">is_just_pushed</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">group_by</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> post </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:#00009f\">cond</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">          post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">version_created </span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"> last_pulled_version </span><span class=\"token keyword\" style=\"color:#00009f\">and</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">is_nil</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">deleted_at_server</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:created</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">          post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">created_at_server </span><span class=\"token operator\" style=\"color:#393A34\">!=</span><span class=\"token plain\"> post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">updated_at_server </span><span class=\"token keyword\" style=\"color:#00009f\">and</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">is_nil</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">deleted_at_server</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:updated</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">          </span><span class=\"token keyword\" style=\"color:#00009f\">not</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">is_nil</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">deleted_at_server</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:deleted</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Map</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">update</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:created</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> posts </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> posts </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Map</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">update</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:updated</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> posts </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> posts </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Map</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">update</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:deleted</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> posts </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> posts </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">map</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> post </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">id </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    latest_version </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">find_latest_version</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">posts_latest</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token attr-name\" style=\"color:#00a4db\">latest_version:</span><span class=\"token plain\"> latest_version</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token attr-name\" style=\"color:#00a4db\">changes:</span><span class=\"token plain\"> posts_changes</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">defp</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">find_latest_version</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">posts</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    posts</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">flat_map</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> post </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">version</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">version_created</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">max</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">fn</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">0</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># ...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">defp</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">is_just_pushed</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">_post</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">when</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">is_nil</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token attr-name\" style=\"color:#00a4db\">do:</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">false</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">defp</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">is_just_pushed</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">post</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> push_id</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token attr-name\" style=\"color:#00a4db\">do:</span><span class=\"token plain\"> post</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">push_id </span><span class=\"token operator\" style=\"color:#393A34\">==</span><span class=\"token plain\"> push_id</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"run-the-backend\">Run the Backend<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#run-the-backend\" class=\"hash-link\" aria-label=\"Direct link to Run the Backend\" title=\"Direct link to Run the Backend\" translate=\"no\">​</a></h3>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix phx.server</span><br></div></code></pre></div></div>\n<p>Sync endpoint will be available on</p>\n<ul>\n<li class=\"\">push: <code>POST http://localhost:4000/api/sync/push?lastPulledVersion=&lt;lastPulledVersion&gt;</code></li>\n<li class=\"\">pull: <code>GET http://localhost:4000/api/sync/pull?lastPulledVersion=&lt;lastPulledVersion&gt;</code></li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"whats-next-\">What's Next ?<a href=\"https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/#whats-next-\" class=\"hash-link\" aria-label=\"Direct link to What's Next ?\" title=\"Direct link to What's Next ?\" translate=\"no\">​</a></h2>\n<p>We have build a sync backend for WatermelonDB frontend application.\nOn the next post, we will continue to code the frontend application with sync capability: <a class=\"\" href=\"https://fahri.blog/posts/building-an-offline-first-react-web-app-using-watermelondb-in-phoenix-elixir/\">Building an Offline First React Web App Using WatermelonDB in Phoenix (Elixir)</a></p>",
            "url": "https://fahri.blog/posts/how-to-build-watermelondb-sync-backend-in-elixir/",
            "title": "How to Build WatermelonDB Sync Backend in Elixir",
            "summary": "WatermelonDB is a reactive database for React frontend application that supports data synchronization. This tutorial explains the concept and shows step by step how to build sync backend using Phoenix (Elixir).",
            "date_modified": "2020-04-24T14:27:12.000Z",
            "author": {
                "name": "Fahri Nurul Hidayat",
                "url": "https://github.com/fahrinh"
            },
            "tags": [
                "Elixir",
                "Phoenix",
                "WatermelonDB",
                "Sync Backend"
            ]
        },
        {
            "id": "https://fahri.blog/posts/generate-sequential-uuidv4-in-elixir/",
            "content_html": "<p>The idea is simple. Sequential UUIDv4 (128 bit) consists of <code>unix timestamp (32 bit) + random bytes (96 bit)</code></p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"uuidv4\">UUIDv4<a href=\"https://fahri.blog/posts/generate-sequential-uuidv4-in-elixir/#uuidv4\" class=\"hash-link\" aria-label=\"Direct link to UUIDv4\" title=\"Direct link to UUIDv4\" translate=\"no\">​</a></h3>\n<p>Basic form of normal UUIDv4 (128 bit) in hex numbers (32 digits) <sup><a href=\"https://fahri.blog/posts/generate-sequential-uuidv4-in-elixir/#user-content-fn-1-63e938\" id=\"user-content-fnref-1-63e938\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\" class=\"anchorTargetHideOnScrollNavbar_CHQy\">1</a></sup> :</p>\n<div class=\"language-text codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx</span><br></div></code></pre></div></div>\n<ul>\n<li class=\"\">Each digit is 4 bit.</li>\n<li class=\"\"><code>x</code> is any random hexadecimal digit</li>\n<li class=\"\"><code>y</code> is either <code>8</code>, <code>9</code>, <code>A</code>, or <code>B</code></li>\n<li class=\"\"><code>4</code> and <code>y</code> are version flags indicate version 4 UUID <sup><a href=\"https://fahri.blog/posts/generate-sequential-uuidv4-in-elixir/#user-content-fn-2-63e938\" id=\"user-content-fnref-2-63e938\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\" class=\"anchorTargetHideOnScrollNavbar_CHQy\">2</a></sup>\n<ul>\n<li class=\"\"><code>y</code> is 4 bit: <code>10zz</code> where <code>z</code> is random bit. Hence, the possible value of <code>y</code> is <code>1000</code> (<code>8</code>), <code>1001</code> (<code>9</code>), <code>1010</code> (<code>A</code>), <code>1011</code> (<code>B</code>)</li>\n</ul>\n</li>\n</ul>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"sequential-uuidv4\">Sequential UUIDv4<a href=\"https://fahri.blog/posts/generate-sequential-uuidv4-in-elixir/#sequential-uuidv4\" class=\"hash-link\" aria-label=\"Direct link to Sequential UUIDv4\" title=\"Direct link to Sequential UUIDv4\" translate=\"no\">​</a></h3>\n<p>A bit modification on normal form where first 32 bits are UNIX timestamp (or 8 digit in hex number) and remaining bits comply with UUIDv4 spec as explained above.</p>\n<div class=\"language-text codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">tttttttt-xxxx-4xxx-yxxx-xxxxxxxxxxxx</span><br></div></code></pre></div></div>\n<ul>\n<li class=\"\"><code>t</code> is UNIX timestamp in hex digit</li>\n</ul>\n<p>Or in binary representation, the 128-bit sequential UUIDv4 consists of five segments:</p>\n<div class=\"language-text codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">[unixtime:32][random:16]['4':4][random:12]['2'(first two bits of `y`):2][random:62]</span><br></div></code></pre></div></div>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"implementation-in-elixir\">Implementation in Elixir<a href=\"https://fahri.blog/posts/generate-sequential-uuidv4-in-elixir/#implementation-in-elixir\" class=\"hash-link\" aria-label=\"Direct link to Implementation in Elixir\" title=\"Direct link to Implementation in Elixir\" translate=\"no\">​</a></h4>\n<p>Thanks to binary pattern matching. The implementation in Elixir is trivial.</p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">SeqUUIDv4</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">generate</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    unix_time </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token module class-name\">DateTime</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">utc_now</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">DateTime</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">to_unix</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">&lt;&lt;</span><span class=\"token plain\">_r0</span><span class=\"token operator\" style=\"color:#393A34\">::</span><span class=\"token number\" style=\"color:#36acaa\">32</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> r1</span><span class=\"token operator\" style=\"color:#393A34\">::</span><span class=\"token number\" style=\"color:#36acaa\">16</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> _r2</span><span class=\"token operator\" style=\"color:#393A34\">::</span><span class=\"token number\" style=\"color:#36acaa\">4</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> r3</span><span class=\"token operator\" style=\"color:#393A34\">::</span><span class=\"token number\" style=\"color:#36acaa\">12</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> _r4</span><span class=\"token operator\" style=\"color:#393A34\">::</span><span class=\"token number\" style=\"color:#36acaa\">2</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> r5</span><span class=\"token operator\" style=\"color:#393A34\">::</span><span class=\"token number\" style=\"color:#36acaa\">62</span><span class=\"token punctuation\" style=\"color:#393A34\">&gt;&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:crypto</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">strong_rand_bytes</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token number\" style=\"color:#36acaa\">16</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">&lt;&lt;</span><span class=\"token plain\">unix_time</span><span class=\"token operator\" style=\"color:#393A34\">::</span><span class=\"token number\" style=\"color:#36acaa\">32</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> r1</span><span class=\"token operator\" style=\"color:#393A34\">::</span><span class=\"token number\" style=\"color:#36acaa\">16</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">4</span><span class=\"token operator\" style=\"color:#393A34\">::</span><span class=\"token number\" style=\"color:#36acaa\">4</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> r3</span><span class=\"token operator\" style=\"color:#393A34\">::</span><span class=\"token number\" style=\"color:#36acaa\">12</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">2</span><span class=\"token operator\" style=\"color:#393A34\">::</span><span class=\"token number\" style=\"color:#36acaa\">2</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> r5</span><span class=\"token operator\" style=\"color:#393A34\">::</span><span class=\"token number\" style=\"color:#36acaa\">62</span><span class=\"token punctuation\" style=\"color:#393A34\">&gt;&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<p>The output of <code>generate/0</code> is binary.\nTo encode as hex numbers use <code>Base.encode16/1</code>:</p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token module class-name\">SeqUUIDv4</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">generate</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Base</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">encode16</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><br></div></code></pre></div></div>\n<!-- -->\n<section data-footnotes=\"\" class=\"footnotes\"><h2 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy sr-only\" id=\"footnote-label\">Footnotes<a href=\"https://fahri.blog/posts/generate-sequential-uuidv4-in-elixir/#footnote-label\" class=\"hash-link\" aria-label=\"Direct link to Footnotes\" title=\"Direct link to Footnotes\" translate=\"no\">​</a></h2>\n<ol>\n<li class=\"anchorTargetHideOnScrollNavbar_CHQy\" id=\"user-content-fn-1-63e938\">\n<p><a href=\"https://stackoverflow.com/questions/19989481/how-to-determine-if-a-string-is-a-valid-v4-uuid/19989922#19989922\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://stackoverflow.com/questions/19989481/how-to-determine-if-a-string-is-a-valid-v4-uuid/19989922#19989922</a> <a href=\"https://fahri.blog/posts/generate-sequential-uuidv4-in-elixir/#user-content-fnref-1-63e938\" data-footnote-backref=\"\" aria-label=\"Back to reference 1\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n<li class=\"anchorTargetHideOnScrollNavbar_CHQy\" id=\"user-content-fn-2-63e938\">\n<p><a href=\"http://tools.ietf.org/html/rfc4122#section-4.4\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">http://tools.ietf.org/html/rfc4122#section-4.4</a> <a href=\"https://fahri.blog/posts/generate-sequential-uuidv4-in-elixir/#user-content-fnref-2-63e938\" data-footnote-backref=\"\" aria-label=\"Back to reference 2\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>",
            "url": "https://fahri.blog/posts/generate-sequential-uuidv4-in-elixir/",
            "title": "Generate Sequential UUIDv4 in Elixir",
            "summary": "Generate time-ordered UUIDv4 values in Elixir using a Unix timestamp prefix.",
            "date_modified": "2020-04-19T05:38:13.000Z",
            "author": {
                "name": "Fahri Nurul Hidayat",
                "url": "https://github.com/fahrinh"
            },
            "tags": [
                "Elixir",
                "UUIDv4"
            ]
        },
        {
            "id": "https://fahri.blog/posts/file-downloading-in-headless-chrome-using-chromedriver-and-hound/",
            "content_html": "<p>Recently, I am making a simple Elixir application performing some actions to a website in an automated way.</p>\n<p>The automated testing tool is a perfect candidate to be used to help to build application like that.\nI use <a href=\"https://github.com/HashNuke/hound\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Hound</a> as browser automation library\nand Chrome as a controlled browser.\nFor the browser driver, I use <a href=\"https://chromedriver.chromium.org/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">ChromeDriver</a>.</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"problem\">Problem<a href=\"https://fahri.blog/posts/file-downloading-in-headless-chrome-using-chromedriver-and-hound/#problem\" class=\"hash-link\" aria-label=\"Direct link to Problem\" title=\"Direct link to Problem\" translate=\"no\">​</a></h2>\n<p>Back to building my application.</p>\n<p>One of the tasks my application doing is downloading a file on the website.\nThat is not a problem in a normal setup. However, the file is not downloaded when\nthe headless mode is enabled.</p>\n<p>After Google has enlightened me, in security perspective, that behaviour is\nneeded to prevent\nmalicious website quietly download unwanted files through the browser in headless mode.</p>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"solution\">Solution<a href=\"https://fahri.blog/posts/file-downloading-in-headless-chrome-using-chromedriver-and-hound/#solution\" class=\"hash-link\" aria-label=\"Direct link to Solution\" title=\"Direct link to Solution\" translate=\"no\">​</a></h2>\n<p>For the solution, we have to instruct ChromeDriver via REST API to allow file downloading</p>\n<div class=\"language-text codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">POST http://localhost:9515/session/&lt;session_id&gt;/chromium/send_command</span><br></div></code></pre></div></div>\n<div class=\"language-json codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-json codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:#36acaa\">\"cmd\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Page.setDownloadBehavior\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:#36acaa\">\"params\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token property\" style=\"color:#36acaa\">\"behavior\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"allow\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token property\" style=\"color:#36acaa\">\"downloadPath\"</span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"/path/download\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<p><em>Note:</em>  <code>9515</code> is ChromeDriver default port</p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"using-hound\">Using Hound<a href=\"https://fahri.blog/posts/file-downloading-in-headless-chrome-using-chromedriver-and-hound/#using-hound\" class=\"hash-link\" aria-label=\"Direct link to Using Hound\" title=\"Direct link to Using Hound\" translate=\"no\">​</a></h3>\n<p>Unfortunately, Hound does not provide <code>send_command</code> as its API method. But, we\ncan use <code>Hound.RequestUtils.make_req</code> to send API request to ChromeDriver.</p>\n<p>For the complete demonstration, these are steps to build a sample application that\ndownload file (<code>Docs.zip</code>) in <a href=\"https://elixir-lang.org/docs.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://elixir-lang.org/docs.html</a></p>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"chrome--chromedriver-setup\">Chrome &amp; ChromeDriver Setup<a href=\"https://fahri.blog/posts/file-downloading-in-headless-chrome-using-chromedriver-and-hound/#chrome--chromedriver-setup\" class=\"hash-link\" aria-label=\"Direct link to Chrome &amp; ChromeDriver Setup\" title=\"Direct link to Chrome &amp; ChromeDriver Setup\" translate=\"no\">​</a></h4>\n<ul>\n<li class=\"\">\n<p>Download and install Chrome</p>\n</li>\n<li class=\"\">\n<p>Download and install\n<a href=\"https://chromedriver.chromium.org/downloads\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">ChromeDriver</a>. Make sure Chrome\nand ChromeDriver have same major version.</p>\n</li>\n<li class=\"\">\n<p>Start ChromeDriver and leave it running:</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ chromedriver </span><span class=\"token parameter variable\" style=\"color:#36acaa\">--verbose</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  Starting ChromeDriver </span><span class=\"token number\" style=\"color:#36acaa\">77.0</span><span class=\"token plain\">.3865.40 </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">f484704e052e0b556f8030b65b953dce96503217-refs/branch-heads/3865@</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\">#442</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> on port </span><span class=\"token number\" style=\"color:#36acaa\">9515</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  Only </span><span class=\"token builtin class-name\">local</span><span class=\"token plain\"> connections are allowed.</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  Please protect ports used by ChromeDriver and related </span><span class=\"token builtin class-name\">test</span><span class=\"token plain\"> frameworks to prevent access by malicious code.</span><br></div></code></pre></div></div>\n</li>\n</ul>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"building-application\">Building Application<a href=\"https://fahri.blog/posts/file-downloading-in-headless-chrome-using-chromedriver-and-hound/#building-application\" class=\"hash-link\" aria-label=\"Direct link to Building Application\" title=\"Direct link to Building Application\" translate=\"no\">​</a></h4>\n<p>Generate a new application</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix new file_downloader</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token builtin class-name\">cd</span><span class=\"token plain\"> file_downloader</span><br></div></code></pre></div></div>\n<p>Add <code>hound</code> as a dependency library</p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># file_downloader/mix.exs</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">FileDownloader</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">MixProject</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">use</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Mix</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Project</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> project </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token attr-name\" style=\"color:#00a4db\">app:</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:file_downloader</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token attr-name\" style=\"color:#00a4db\">version:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"0.1.0\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token attr-name\" style=\"color:#00a4db\">elixir:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"~&gt; 1.9\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token attr-name\" style=\"color:#00a4db\">start_permanent:</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Mix</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">env</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">==</span><span class=\"token plain\"> </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:prod</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token attr-name\" style=\"color:#00a4db\">deps:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">deps</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> application </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token attr-name\" style=\"color:#00a4db\">extra_applications:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:logger</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">defp</span><span class=\"token plain\"> deps </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:hound</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"~&gt; 1.1.0\"</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># &lt;- add hound library</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<p>Download the dependencies</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix deps.gets</span><br></div></code></pre></div></div>\n<p>Config <code>hound</code> to use ChromeDriver and Chrome in headless mode</p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># file_downloader/config/config.exs</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">use</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Mix</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Config</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">config </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:hound</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token attr-name\" style=\"color:#00a4db\">driver:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"chrome_driver\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token attr-name\" style=\"color:#00a4db\">browser:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"chrome_headless\"</span><br></div></code></pre></div></div>\n<p>Code the logic of our application. Step 3 describes how to enable file downloading in\nheadless mode.</p>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># file_downloader/lib/file_downloader.ex</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">FileDownloader</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">use</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Hound</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">Helpers</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Hound</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token module class-name\">RequestUtils</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">def</span><span class=\"token plain\"> download_elixir_docs </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># 1) Start hound session</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token module class-name\">Hound</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">start_session</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># 2) Visit the website</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:#d73a49\">navigate_to</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"https://elixir-lang.org/docs.html\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># 3) By using 'Hound.RequestUtils.make_req', enable file downloading</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:ok</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> download_path</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token module class-name\">File</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">cwd</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    session_id </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Hound</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">current_session_id</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:#d73a49\">make_req</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token atom symbol\" style=\"color:#36acaa\">:post</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token string\" style=\"color:#e3116c\">\"session/</span><span class=\"token string interpolation delimiter punctuation\" style=\"color:#393A34\">#{</span><span class=\"token string interpolation\" style=\"color:#e3116c\">session_id</span><span class=\"token string interpolation delimiter punctuation\" style=\"color:#393A34\">}</span><span class=\"token string\" style=\"color:#e3116c\">/chromium/send_command\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token attr-name\" style=\"color:#00a4db\">cmd:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Page.setDownloadBehavior\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token attr-name\" style=\"color:#00a4db\">params:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">%</span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token attr-name\" style=\"color:#00a4db\">behavior:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"allow\"</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token attr-name\" style=\"color:#00a4db\">downloadPath:</span><span class=\"token plain\"> download_path</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># 4) Find download link and click it to download file</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    download_link </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token atom symbol\" style=\"color:#36acaa\">:xpath</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"//*[@id='stable']/small/a\"</span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    download_link </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">click</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># 5) Wait until download process is completed</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:#d73a49\">wait_download_started</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">download_path</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:#d73a49\">wait_download_completed</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">download_path</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># 6) Stop hound session</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token module class-name\">Hound</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">end_session</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">defp</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">wait_download_started</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">download_path</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:#d73a49\">wait_crdownload</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">download_path</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">true</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">defp</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">wait_download_completed</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">download_path</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:#d73a49\">wait_crdownload</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">download_path</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:#36acaa\">false</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">defp</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">wait_crdownload</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">dir</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> exist?</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> wait_time </span><span class=\"token operator\" style=\"color:#393A34\">\\\\</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1000</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    count_crdownload </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      dir</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Path</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">join</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"*.crdownload\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Path</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">wildcard</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:#393A34\">|&gt;</span><span class=\"token plain\"> </span><span class=\"token module class-name\">Enum</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">count</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:#d73a49\">unless</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">count_crdownload </span><span class=\"token operator\" style=\"color:#393A34\">!=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">0</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">&amp;&amp;</span><span class=\"token plain\"> exist?</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">||</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">count_crdownload </span><span class=\"token operator\" style=\"color:#393A34\">==</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">0</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">&amp;&amp;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">!</span><span class=\"token plain\">exist?</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token module class-name\">Process</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">sleep</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">wait_time</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token function\" style=\"color:#d73a49\">wait_crdownload</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">dir</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> exist?</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> wait_time</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">end</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<hr>\n<p>Full source code:\n<a href=\"https://github.com/fahrinh/blog-labs/tree/master/2019-09-16/file_downloader\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://github.com/fahrinh/blog-labs/tree/master/2019-09-16/file_downloader</a></p>\n<hr>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"running-the-application\">Running the Application<a href=\"https://fahri.blog/posts/file-downloading-in-headless-chrome-using-chromedriver-and-hound/#running-the-application\" class=\"hash-link\" aria-label=\"Direct link to Running the Application\" title=\"Direct link to Running the Application\" translate=\"no\">​</a></h4>\n<p>Run the application and wait until it is finished.</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix run </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-e</span><span class=\"token plain\"> FileDownloader.download_elixir_docs</span><br></div></code></pre></div></div>\n<p>The downloaded file (<code>Docs.zip</code>) will be available in the current directory (<code>file_downloader</code>).</p>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"troubleshooting\">Troubleshooting<a href=\"https://fahri.blog/posts/file-downloading-in-headless-chrome-using-chromedriver-and-hound/#troubleshooting\" class=\"hash-link\" aria-label=\"Direct link to Troubleshooting\" title=\"Direct link to Troubleshooting\" translate=\"no\">​</a></h4>\n<p>If you got a runtime error (invalid session id) like this :</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ mix run </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-e</span><span class=\"token plain\"> FileDownloader.download_elixir_docs</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Compiling </span><span class=\"token number\" style=\"color:#36acaa\">1</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">file</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">.ex</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">** </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">RuntimeError</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> invalid session </span><span class=\"token function\" style=\"color:#d73a49\">id</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">hound</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> lib/hound/request_utils.ex:52: Hound.RequestUtils.handle_response/3</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">file_downloader</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> lib/file_downloader.ex:13: FileDownloader.download_elixir_docs/0</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">stdlib</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> erl_eval.erl:680: :erl_eval.do_apply/6</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">elixir</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> lib/code.ex:240: Code.eval_string/3</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">elixir</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> lib/enum.ex:783: Enum.</span><span class=\"token string\" style=\"color:#e3116c\">\"-each/2-lists^foreach/1-0-\"</span><span class=\"token plain\">/2</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">elixir</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> lib/enum.ex:783: Enum.each/2</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">mix</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> lib/mix/tasks/run.ex:141: Mix.Tasks.Run.run/5</span><br></div></code></pre></div></div>\n<p>it might be caused by different versions of Chrome and ChromeDriver.\nYou can check the log of running ChromeDriver.</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ chromedriver </span><span class=\"token parameter variable\" style=\"color:#36acaa\">--verbose</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">..</span><span class=\"token plain\">.</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token number\" style=\"color:#36acaa\">1578222297.224</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">INFO</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\">: Failed to connect to Chrome. Attempting to </span><span class=\"token function\" style=\"color:#d73a49\">kill</span><span class=\"token plain\"> it.</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token number\" style=\"color:#36acaa\">1578222297.244</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">INFO</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\">: </span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token plain\">e5d2ce77a1b56643db3d11b6fad7d946</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> RESPONSE InitSession ERROR session not created: This version of ChromeDriver only supports Chrome version </span><span class=\"token number\" style=\"color:#36acaa\">77</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">..</span><span class=\"token plain\">.</span><br></div></code></pre></div></div>",
            "url": "https://fahri.blog/posts/file-downloading-in-headless-chrome-using-chromedriver-and-hound/",
            "title": "File Downloading in Headless Chrome Using ChromeDriver and Hound",
            "summary": "Download files from a website using headless Chrome, ChromeDriver, and Hound in Elixir.",
            "date_modified": "2019-09-16T06:10:45.000Z",
            "author": {
                "name": "Fahri Nurul Hidayat",
                "url": "https://github.com/fahrinh"
            },
            "tags": [
                "Elixir",
                "Headless Chrome",
                "ChromeDriver",
                "Hound"
            ]
        },
        {
            "id": "https://fahri.blog/posts/how-to-update-pomera-dm100-firmware/",
            "content_html": "<p>Pomera DM100 is a distraction-free digital writing tool. Think mini laptop with only text editor application loaded.</p>\n<p>It comes from Japan. It means its manual is in all Japanese. It becomes hard when you want to do the crucial procedure (like <strong>upgrading firmware</strong>) <strong>AND</strong> Google Translate doesn't help you much.</p>\n<p>I can only follow some steps in <a href=\"https://translate.google.co.id/translate?hl=en&amp;sl=ja&amp;u=http://www.kingjim.co.jp/support/pomera/software/dm100&amp;prev=search\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">its updating guide web page</a> and the rest of important steps in <a href=\"http://www.kingjim.co.jp/resource/media/support/pomera/update_dm100.pdf\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">PDF</a> are not translatable by Google Translate.</p>\n<p>In the end, I have successfully updated my Pomera DM100 to the latest firmware.</p>\n<p>Here are the steps:</p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"prerequisites\">Prerequisites<a href=\"https://fahri.blog/posts/how-to-update-pomera-dm100-firmware/#prerequisites\" class=\"hash-link\" aria-label=\"Direct link to Prerequisites\" title=\"Direct link to Prerequisites\" translate=\"no\">​</a></h3>\n<ol>\n<li class=\"\">\n<p>An SD Card.</p>\n<p>Make sure you have backed up your data in this SD card <strong>AND</strong> in the internal memory of Pomera DM100</p>\n</li>\n<li class=\"\">\n<p>An USB 2.0 A to Mini-B cable.</p>\n</li>\n</ol>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"steps-to-update-firmware\">Steps to Update Firmware<a href=\"https://fahri.blog/posts/how-to-update-pomera-dm100-firmware/#steps-to-update-firmware\" class=\"hash-link\" aria-label=\"Direct link to Steps to Update Firmware\" title=\"Direct link to Steps to Update Firmware\" translate=\"no\">​</a></h3>\n<ol>\n<li class=\"\">\n<p>Download the latest firmware : <a href=\"https://www.kingjim.co.jp/resource-files/download/pomera/dm100/DM100_V15000.zip\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://www.kingjim.co.jp/resource-files/download/pomera/dm100/DM100_V15000.zip</a></p>\n</li>\n<li class=\"\">\n<p>Extract the zip file</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">unzip</span><span class=\"token plain\"> DM100_V15000.zip</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Archive:  DM100_V15000.zip</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">inflating: DM100_V15000/Pomera_Update_Dm100_V15000.bin</span><br></div></code></pre></div></div>\n</li>\n<li class=\"\">\n<p>Format the SD card as <strong>MS-DOS (FAT)</strong> and set name to <strong>POMERA</strong>.\nOn Mac :</p>\n<ol>\n<li class=\"\">Open <strong>Disk Utility</strong></li>\n<li class=\"\">In sidebar, make sure you choose your SD Card</li>\n<li class=\"\">Click <code>Erase</code> on header bar menus</li>\n<li class=\"\">Set <code>Name</code> to <strong>POMERA</strong></li>\n<li class=\"\"><code>Format</code> as <strong>MS-DOS (FAT)</strong></li>\n<li class=\"\">Click <code>Erase</code> button\n<img decoding=\"async\" loading=\"lazy\" alt=\"disk-utility\" src=\"https://fahri.blog/assets/images/pomera-disk-utility-5180183426a25cac6daaa8ff3702431c.png\" width=\"932\" height=\"865\" class=\"img_nsRP\"></li>\n</ol>\n</li>\n<li class=\"\">\n<p>Copy <code>Pomera_Update_Dm100_V15000.bin</code> to the SD card</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">cp</span><span class=\"token plain\"> DM100_V15000/Pomera_Update_Dm100_V15000.bin /Volumes/POMERA/</span><br></div></code></pre></div></div>\n</li>\n<li class=\"\">\n<p>Connect Pomera DM100 to PC using USB A to Mini-B cable</p>\n</li>\n<li class=\"\">\n<p>Update firmware on Pomera DM100</p>\n<ol>\n<li class=\"\">Open Pomera DM100</li>\n<li class=\"\">Click <code>Menu</code> button on the device</li>\n<li class=\"\"><code>Setting</code> &gt; <code>About DM100</code></li>\n<li class=\"\">Press <code>F1</code></li>\n</ol>\n</li>\n<li class=\"\">\n<p>Updating process will begin. Wait until following dialog appears. (<em>Update is complete. Disconnect the USB cable to restart the DM100</em>)\n<img decoding=\"async\" loading=\"lazy\" alt=\"reduced-1-updated-complete\" src=\"https://fahri.blog/assets/images/pomera-reduced-1-updated-complete-9d9f403791338d946129dbcb83a73c7b.jpg\" width=\"4032\" height=\"3024\" class=\"img_nsRP\"></p>\n</li>\n<li class=\"\">\n<p>Disconnect the USB cable. Wait until the reboot has finished.</p>\n</li>\n<li class=\"\">\n<p>After restarted, a dialog appears. It means we have to <strong>connect again USB cable to the PC</strong>\n<img decoding=\"async\" loading=\"lazy\" alt=\"reduced-2-connect-again\" src=\"https://fahri.blog/assets/images/pomera-reduced-2-connect-again-4bebbedd12c9ce60ff56a0e41c144a6e.jpg\" width=\"4032\" height=\"3024\" class=\"img_nsRP\"></p>\n</li>\n<li class=\"\">\n<p>Updating process continues.\n<img decoding=\"async\" loading=\"lazy\" alt=\"reduced-3-update-continues\" src=\"https://fahri.blog/assets/images/pomera-reduced-3-update-continues-8502e69c97d91d945b4f898ab70d8998.jpg\" width=\"4032\" height=\"3024\" class=\"img_nsRP\"></p>\n</li>\n<li class=\"\">\n<p>If succeeded, the main screen is displayed. We can unplug the USB cable. <strong>DONE</strong></p>\n</li>\n</ol>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"change-display-language\">Change Display Language<a href=\"https://fahri.blog/posts/how-to-update-pomera-dm100-firmware/#change-display-language\" class=\"hash-link\" aria-label=\"Direct link to Change Display Language\" title=\"Direct link to Change Display Language\" translate=\"no\">​</a></h3>\n<p>But it seems reverted back to the original setting, Japanese as display language. To set English as display language :</p>\n<ol>\n<li class=\"\">Click <code>Menu</code> button on the device</li>\n<li class=\"\">Choose top-right menu then choose <code>Language</code>. Pick <code>English</code> then click <code>Enter</code></li>\n</ol>",
            "url": "https://fahri.blog/posts/how-to-update-pomera-dm100-firmware/",
            "title": "How to Update Pomera DM100 Firmware",
            "summary": "Step-by-step guide to updating the Pomera DM100 firmware.",
            "date_modified": "2017-11-21T23:13:35.000Z",
            "author": {
                "name": "Fahri Nurul Hidayat",
                "url": "https://github.com/fahrinh"
            },
            "tags": [
                "Gear",
                "Pomera DM100"
            ]
        },
        {
            "id": "https://fahri.blog/posts/java-how-to-autodetect-the-charset/",
            "content_html": "<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"tldr\">TLDR;<a href=\"https://fahri.blog/posts/java-how-to-autodetect-the-charset/#tldr\" class=\"hash-link\" aria-label=\"Direct link to TLDR;\" title=\"Direct link to TLDR;\" translate=\"no\">​</a></h3>\n<p>Required dependencies (<code>pom.xml</code>) :</p>\n<div class=\"language-markup codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-markup codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">dependency</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">groupId</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\">com.ibm.icu</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">groupId</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">artifactId</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\">icu4j</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">artifactId</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">version</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\">60.1</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">version</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">dependency</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">dependency</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">groupId</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\">commons-io</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">groupId</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">artifactId</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\">commons-io</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">artifactId</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;</span><span class=\"token tag\" style=\"color:#00009f\">version</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\">2.6</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">version</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:#393A34\">&lt;/</span><span class=\"token tag\" style=\"color:#00009f\">dependency</span><span class=\"token tag punctuation\" style=\"color:#393A34\">&gt;</span><br></div></code></pre></div></div>\n<p>Autodetect the charset encoding of a text file or input stream then 'remove' (skip) Byte Order Mark (BOM) while reading based on detected charset  :</p>\n<div class=\"language-java codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-java codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token class-name\">File</span><span class=\"token plain\"> inputFile </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\">File</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"/Users/fahri/Downloads/UNKNOWN_TEXT.txt\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token class-name\">BOMInputStream</span><span class=\"token plain\"> bomInputStream </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\">BOMInputStream</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\">BufferedInputStream</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\">FileInputStream</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">inputFile</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">        </span><span class=\"token class-name\">ByteOrderMark</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token constant\" style=\"color:#36acaa\">UTF_8</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token class-name\">ByteOrderMark</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token constant\" style=\"color:#36acaa\">UTF_16BE</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token class-name\">ByteOrderMark</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token constant\" style=\"color:#36acaa\">UTF_16LE</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token class-name\">ByteOrderMark</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token constant\" style=\"color:#36acaa\">UTF_32BE</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> </span><span class=\"token class-name\">ByteOrderMark</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token constant\" style=\"color:#36acaa\">UTF_32LE</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token class-name\">System</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">out</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">println</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"HAS BOM : \"</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">+</span><span class=\"token plain\"> bomInputStream</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">hasBOM</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token class-name\">CharsetDetector</span><span class=\"token plain\"> detector </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\">CharsetDetector</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">detector</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">setText</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">bomInputStream</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token class-name\">CharsetMatch</span><span class=\"token plain\"> charsetMatch </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> detector</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">detect</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token class-name\">System</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">out</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">println</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"CHARSET MATCH : \"</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:#393A34\">+</span><span class=\"token plain\"> charsetMatch</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">getName</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token class-name\">BufferedReader</span><span class=\"token plain\"> br </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\">BufferedReader</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token keyword\" style=\"color:#00009f\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\">InputStreamReader</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">bomInputStream</span><span class=\"token punctuation\" style=\"color:#393A34\">,</span><span class=\"token plain\"> charsetMatch</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">getName</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">for</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token class-name\">String</span><span class=\"token plain\"> line </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> br</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">readLine</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"> line </span><span class=\"token operator\" style=\"color:#393A34\">!=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">null</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"> line </span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\"> br</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">readLine</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token class-name\">System</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">out</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">println</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">line</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">br</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">close</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"problem\">Problem<a href=\"https://fahri.blog/posts/java-how-to-autodetect-the-charset/#problem\" class=\"hash-link\" aria-label=\"Direct link to Problem\" title=\"Direct link to Problem\" translate=\"no\">​</a></h3>\n<p>You got a text file and you have no idea why your application could not process (parse) that file.</p>\n<p>This is a sample of that file:  <a href=\"https://github.com/fahrinh/fahrinh.github.io/files/1451863/UNKNOWN_TEXT.txt\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">UNKNOWN_TEXT.txt</a></p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"analyze-the-content\">Analyze The Content<a href=\"https://fahri.blog/posts/java-how-to-autodetect-the-charset/#analyze-the-content\" class=\"hash-link\" aria-label=\"Direct link to Analyze The Content\" title=\"Direct link to Analyze The Content\" translate=\"no\">​</a></h3>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"cat\"><code>cat</code><a href=\"https://fahri.blog/posts/java-how-to-autodetect-the-charset/#cat\" class=\"hash-link\" aria-label=\"Direct link to cat\" title=\"Direct link to cat\" translate=\"no\">​</a></h4>\n<p>If we inspect the content using <code>cat</code> :</p>\n<p><img decoding=\"async\" loading=\"lazy\" alt=\"ss-cat-unknown\" src=\"https://fahri.blog/assets/images/java-ss-cat-unknown-72d9cd7e6ebb388865aec958eed539c8.png\" width=\"392\" height=\"55\" class=\"img_nsRP\"></p>\n<p>The content looks normal. <em>But, wait</em>.<br>\nWhat is that weird characters at the beginning and end ? (<code>��</code> and <code>%</code>)</p>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"more\"><code>more</code><a href=\"https://fahri.blog/posts/java-how-to-autodetect-the-charset/#more\" class=\"hash-link\" aria-label=\"Direct link to more\" title=\"Direct link to more\" translate=\"no\">​</a></h4>\n<p>Display the content using another tool, <code>more</code> :\n<img decoding=\"async\" loading=\"lazy\" alt=\"ss-more-unknown\" src=\"https://fahri.blog/assets/images/java-ss-more-unknown-64c94f101fc99c6272b0b9779ba5e793.png\" width=\"570\" height=\"56\" class=\"img_nsRP\"></p>\n<p>It looks weirder. <code>&lt;FF&gt;&lt;FE&gt;</code> at the beginning and <code>^@</code> between the characters.</p>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"file\"><code>file</code><a href=\"https://fahri.blog/posts/java-how-to-autodetect-the-charset/#file\" class=\"hash-link\" aria-label=\"Direct link to file\" title=\"Direct link to file\" translate=\"no\">​</a></h4>\n<p>What <code>file</code> command says ?</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">file</span><span class=\"token plain\"> UNKNOWN_TEXT.txt</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">UNKNOWN_TEXT.txt: Little-endian UTF-16 Unicode text  </span><br></div></code></pre></div></div>\n<p>The text file is a Little-Endian UTF-16 text and our viewer (iTerm2 on OSX, in this case) only supports UTF-8. That is why it looks not normal and your application can not process (parse) further.</p>\n<h4 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"hexdump\"><code>hexdump</code><a href=\"https://fahri.blog/posts/java-how-to-autodetect-the-charset/#hexdump\" class=\"hash-link\" aria-label=\"Direct link to hexdump\" title=\"Direct link to hexdump\" translate=\"no\">​</a></h4>\n<p>If we investigate in more detail using <code>hexdump</code> :</p>\n<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ hexdump UNKNOWN_TEXT.txt</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">0000000 ff fe </span><span class=\"token number\" style=\"color:#36acaa\">31</span><span class=\"token plain\"> 00 7c 00 </span><span class=\"token number\" style=\"color:#36acaa\">43</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">65</span><span class=\"token plain\"> 00 6c 00 6c 00 </span><span class=\"token number\" style=\"color:#36acaa\">32</span><span class=\"token plain\"> 00</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">0000010 </span><span class=\"token number\" style=\"color:#36acaa\">31</span><span class=\"token plain\"> 00 7c 00 </span><span class=\"token number\" style=\"color:#36acaa\">31</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">32</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">33</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">34</span><span class=\"token plain\"> 00 7c 00 </span><span class=\"token number\" style=\"color:#36acaa\">32</span><span class=\"token plain\"> 00</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">0000020 </span><span class=\"token number\" style=\"color:#36acaa\">30</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">31</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">37</span><span class=\"token plain\"> 00 2f 00 </span><span class=\"token number\" style=\"color:#36acaa\">31</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">30</span><span class=\"token plain\"> 00 2f 00 </span><span class=\"token number\" style=\"color:#36acaa\">32</span><span class=\"token plain\"> 00</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">0000030 </span><span class=\"token number\" style=\"color:#36acaa\">30</span><span class=\"token plain\"> 00 0a 00 </span><span class=\"token number\" style=\"color:#36acaa\">32</span><span class=\"token plain\"> 00 7c 00 </span><span class=\"token number\" style=\"color:#36acaa\">43</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">65</span><span class=\"token plain\"> 00 6c 00 6c 00</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">0000040 </span><span class=\"token number\" style=\"color:#36acaa\">32</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">32</span><span class=\"token plain\"> 00 7c 00 </span><span class=\"token number\" style=\"color:#36acaa\">35</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">36</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">37</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">38</span><span class=\"token plain\"> 00 7c 00</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">0000050 </span><span class=\"token number\" style=\"color:#36acaa\">32</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">30</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">31</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">37</span><span class=\"token plain\"> 00 2f 00 </span><span class=\"token number\" style=\"color:#36acaa\">31</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">30</span><span class=\"token plain\"> 00 2f 00</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">0000060 </span><span class=\"token number\" style=\"color:#36acaa\">32</span><span class=\"token plain\"> 00 </span><span class=\"token number\" style=\"color:#36acaa\">30</span><span class=\"token plain\"> 00</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">0000064</span><br></div></code></pre></div></div>\n<p>We can conclude that <code>&lt;FF&gt;&lt;FE&gt;</code> and <code>^@</code> represents value <code>ff fe</code> and <code>00</code> in hex, respectively.</p>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"endianness\">Endianness<a href=\"https://fahri.blog/posts/java-how-to-autodetect-the-charset/#endianness\" class=\"hash-link\" aria-label=\"Direct link to Endianness\" title=\"Direct link to Endianness\" translate=\"no\">​</a></h3>\n<p>UTF-16 represents a character using two bytes (2x8 byte=16, make sense, huh?). There are two ways to determine the order of the bytes <sup><a href=\"https://fahri.blog/posts/java-how-to-autodetect-the-charset/#user-content-fn-1-a2616b\" id=\"user-content-fnref-1-a2616b\" data-footnote-ref=\"\" aria-describedby=\"footnote-label\" class=\"anchorTargetHideOnScrollNavbar_CHQy\">1</a></sup> :</p>\n<ul>\n<li class=\"\">Big Endian : you store the most significant byte in the smallest address</li>\n<li class=\"\">Little Endian : you store the least significant byte in the smallest address</li>\n</ul>\n<p>For the concrete example, these are characters <code>Z</code> in various encoding :</p>\n<div class=\"language-text codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">Character                    : Z</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">ASCII (in hex)               : 5A</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">UTF16 Little Endian (in hex) : 5A 00</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">UTF16 Big Endian (in hex)    : 00 5A</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"byte-order-mark-bom\">Byte Order Mark (BOM)<a href=\"https://fahri.blog/posts/java-how-to-autodetect-the-charset/#byte-order-mark-bom\" class=\"hash-link\" aria-label=\"Direct link to Byte Order Mark (BOM)\" title=\"Direct link to Byte Order Mark (BOM)\" translate=\"no\">​</a></h3>\n<p>You already know the meaning of <code>00</code>. Then, what exactly is <code>ff fe</code> in the first bytes ?</p>\n<!-- -->\n<section data-footnotes=\"\" class=\"footnotes\"><h2 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy sr-only\" id=\"footnote-label\">Footnotes<a href=\"https://fahri.blog/posts/java-how-to-autodetect-the-charset/#footnote-label\" class=\"hash-link\" aria-label=\"Direct link to Footnotes\" title=\"Direct link to Footnotes\" translate=\"no\">​</a></h2>\n<ol>\n<li class=\"anchorTargetHideOnScrollNavbar_CHQy\" id=\"user-content-fn-1-a2616b\">\n<p><a href=\"https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html</a> <a href=\"https://fahri.blog/posts/java-how-to-autodetect-the-charset/#user-content-fnref-1-a2616b\" data-footnote-backref=\"\" aria-label=\"Back to reference 1\" class=\"data-footnote-backref\">↩</a></p>\n</li>\n</ol>\n</section>",
            "url": "https://fahri.blog/posts/java-how-to-autodetect-the-charset/",
            "title": "Java: How To Autodetect The Charset Encoding of A Text File and Remove Byte Order Mark (BOM)",
            "summary": "Detect a text file's charset and remove a byte order mark in Java.",
            "date_modified": "2017-11-07T21:42:36.000Z",
            "author": {
                "name": "Fahri Nurul Hidayat",
                "url": "https://github.com/fahrinh"
            },
            "tags": [
                "Java",
                "BOM",
                "Byte Order Mark",
                "Charset Encoding"
            ]
        },
        {
            "id": "https://fahri.blog/posts/oracle-xe-11g-on-docker/",
            "content_html": "<div class=\"language-shell codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-shell codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">docker</span><span class=\"token plain\"> pull wnameless/oracle-xe-11g</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">docker</span><span class=\"token plain\"> run </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-d</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-p</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1022</span><span class=\"token plain\">:22 </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-p</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">1521</span><span class=\"token plain\">:1521 </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-e</span><span class=\"token plain\"> </span><span class=\"token assign-left variable\" style=\"color:#36acaa\">ORACLE_ALLOW_REMOTE</span><span class=\"token operator\" style=\"color:#393A34\">=</span><span class=\"token plain\">true wnameless/oracle-xe-11g</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">docker</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">ps</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:#36acaa\">-a</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS               NAMES</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">4fe7a1024ed3        wnameless/oracle-xe-11g   </span><span class=\"token string\" style=\"color:#e3116c\">\"/bin/sh -c '/usr/...\"</span><span class=\"token plain\">   </span><span class=\"token number\" style=\"color:#36acaa\">5</span><span class=\"token plain\"> weeks ago         Exited </span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token number\" style=\"color:#36acaa\">137</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:#36acaa\">4</span><span class=\"token plain\"> days ago                       practical_williams</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">docker</span><span class=\"token plain\"> start practical_williams</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># or</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">$ </span><span class=\"token function\" style=\"color:#d73a49\">docker</span><span class=\"token plain\"> start 4fe7a1024ed3</span><br></div></code></pre></div></div>\n<p>Database connection configuration:</p>\n<div class=\"language-text codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">hostname: localhost</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">port: 1521</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">sid: xe</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">username: system</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">password: oracle</span><br></div></code></pre></div></div>\n<p>Password for <code>SYS</code> and <code>SYSTEM</code>:</p>\n<div class=\"language-text codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">oracle</span><br></div></code></pre></div></div>\n<p>Log in with SSH:</p>\n<div class=\"language-text codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">ssh root@localhost -p 1022</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">password: admin</span><br></div></code></pre></div></div>\n<p>Source: <a href=\"https://github.com/wnameless/docker-oracle-xe-11g\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://github.com/wnameless/docker-oracle-xe-11g</a></p>",
            "url": "https://fahri.blog/posts/oracle-xe-11g-on-docker/",
            "title": "Oracle XE 11g with Docker",
            "summary": "Run Oracle XE 11g with Docker.",
            "date_modified": "2017-07-22T23:26:06.000Z",
            "author": {
                "name": "Fahri Nurul Hidayat",
                "url": "https://github.com/fahrinh"
            },
            "tags": [
                "Mini Tips",
                "Oracle",
                "Docker"
            ]
        },
        {
            "id": "https://fahri.blog/posts/static-blogging-with-hugo/",
            "content_html": "<h2 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"github\">Github<a href=\"https://fahri.blog/posts/static-blogging-with-hugo/#github\" class=\"hash-link\" aria-label=\"Direct link to Github\" title=\"Direct link to Github\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\">\n<p>Create two repositories on Github:</p>\n<ul>\n<li class=\"\">Content source repository (the result of <code>hugo new site</code>): <a href=\"https://github.com/fahrinh/my-site\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://github.com/fahrinh/my-site</a></li>\n<li class=\"\">Main web pages repository (the result of running Hugo): <a href=\"https://github.com/fahrinh/fahrinh.github.io\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://github.com/fahrinh/fahrinh.github.io</a></li>\n</ul>\n</li>\n<li class=\"\">\n<p>Create a Personal Access Token at <a href=\"https://github.com/settings/tokens\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://github.com/settings/tokens</a> with the <strong>repo</strong> scope. Copy the token to your clipboard.</p>\n</li>\n<li class=\"\">\n<p>Make sure there is a <code>CNAME</code> file containing the custom domain in the <a href=\"https://github.com/fahrinh/my-site\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://github.com/fahrinh/my-site</a> repository.</p>\n</li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"travis-ci\">Travis CI<a href=\"https://fahri.blog/posts/static-blogging-with-hugo/#travis-ci\" class=\"hash-link\" aria-label=\"Direct link to Travis CI\" title=\"Direct link to Travis CI\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\">Create a <code>.travis.yml</code> configuration file in the <a href=\"https://github.com/fahrinh/my-site/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://github.com/fahrinh/my-site/</a> repository with this content:</li>\n</ul>\n<div class=\"language-yaml codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token key atrule\" style=\"color:#00a4db\">language</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> go</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:#00a4db\">go</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> master </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># This uses automatically the latest version of go</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:#00a4db\">install</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> pip install </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">user pygments</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> go get github.com/spf13/hugo </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># This provides the latest version of Hugo to Travis CI</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:#00a4db\">script</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> hugo version</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> hugo </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">theme=hugo</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">pacman</span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\">theme </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># This commands builds your website on travis</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> cp CNAME public</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">-</span><span class=\"token plain\"> ls public</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token key atrule\" style=\"color:#00a4db\">deploy</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">local_dir</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> public </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># Default static site output dir for Hugo</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">repo</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> fahrinh/fahrinh.github.io </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># This is the slug of the repo you want to deploy your site to</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">target_branch</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> master </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># GitHub pages branch to deploy to (in other cases it can be gh-pages)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">provider</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> pages</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">skip_cleanup</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token boolean important\" style=\"color:#36acaa\">true</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">github_token</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> $GITHUB_TOKEN </span><span class=\"token comment\" style=\"color:#999988;font-style:italic\"># This is the authentication which you will setup in the next step in travis-ci dashboard</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">email</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> fahri.cyber@gmail.com</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">name</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Fahri Nurul Hidayat\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token key atrule\" style=\"color:#00a4db\">on</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token key atrule\" style=\"color:#00a4db\">branch</span><span class=\"token punctuation\" style=\"color:#393A34\">:</span><span class=\"token plain\"> master</span><br></div></code></pre></div></div>\n<ul>\n<li class=\"\">Create a <code>GITHUB_TOKEN</code> <strong>Environment Variable</strong> at <a href=\"https://travis-ci.org/fahrinh/my-site/settings\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://travis-ci.org/fahrinh/my-site/settings</a> with the Personal Access Token you created earlier.</li>\n</ul>\n<h2 class=\"anchor anchorTargetHideOnScrollNavbar_CHQy\" id=\"cloudflare\">Cloudflare<a href=\"https://fahri.blog/posts/static-blogging-with-hugo/#cloudflare\" class=\"hash-link\" aria-label=\"Direct link to Cloudflare\" title=\"Direct link to Cloudflare\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\">Set up DNS with the root domain <code>nurul.id</code></li>\n<li class=\"\">Replace your hosting provider's nameservers with Cloudflare's nameservers</li>\n<li class=\"\">Under <strong>Crypto</strong>, enable <strong>Always use HTTPS</strong> and <strong>Automatic HTTPS Rewrites</strong></li>\n</ul>\n<p>Source: <a href=\"https://martinkaptein.github.io/blog/hugo-with-travis-ci-on-gh-pages/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://martinkaptein.github.io/blog/hugo-with-travis-ci-on-gh-pages/</a></p>",
            "url": "https://fahri.blog/posts/static-blogging-with-hugo/",
            "title": "Static Blogging with Hugo, GitHub Pages (Travis CI, Cloudflare)",
            "summary": "Set up a static blog with Hugo, GitHub Pages, Travis CI, and Cloudflare.",
            "date_modified": "2017-07-22T14:02:09.000Z",
            "author": {
                "name": "Fahri Nurul Hidayat",
                "url": "https://github.com/fahrinh"
            },
            "tags": [
                "Hugo",
                "Github Pages",
                "Travis CI"
            ]
        },
        {
            "id": "https://fahri.blog/posts/hello-world/",
            "content_html": "<div class=\"language-java codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-java codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">class</span><span class=\"token plain\"> </span><span class=\"token class-name\">HelloWorld</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:#00009f\">static</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">public</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">void</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">main</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"> </span><span class=\"token class-name\">String</span><span class=\"token plain\"> args</span><span class=\"token punctuation\" style=\"color:#393A34\">[</span><span class=\"token punctuation\" style=\"color:#393A34\">]</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token class-name\">System</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">out</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">println</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"Hello World!\"</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<div class=\"language-kotlin codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-kotlin codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">fun</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">main</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token plain\">args </span><span class=\"token operator\" style=\"color:#393A34\">:</span><span class=\"token plain\"> Array</span><span class=\"token operator\" style=\"color:#393A34\">&lt;</span><span class=\"token plain\">String</span><span class=\"token operator\" style=\"color:#393A34\">&gt;</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:#d73a49\">println</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string-literal singleline string\" style=\"color:#e3116c\">\"Hello, world!\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<div class=\"language-javascript codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token console class-name\">console</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token method function property-access\" style=\"color:#d73a49\">log</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"Hello World\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token punctuation\" style=\"color:#393A34\">;</span><br></div></code></pre></div></div>\n<div class=\"language-elixir codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-elixir codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">defmodule</span><span class=\"token plain\"> </span><span class=\"token module class-name\">HelloWorld</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:#00009f\">do</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  </span><span class=\"token module class-name\">IO</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token plain\">puts </span><span class=\"token string\" style=\"color:#e3116c\">\"Hello, World!\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">end</span><br></div></code></pre></div></div>\n<div class=\"language-go codeBlockContainer_z0PW theme-code-block\" style=\"--prism-color:#393A34;--prism-background-color:#f6f8fa\"><div class=\"codeBlockContent_lZ2Q\"><pre tabindex=\"0\" class=\"prism-code language-go codeBlock_LRRW thin-scrollbar\" style=\"color:#393A34;background-color:#f6f8fa\"><code class=\"codeBlockLines_pUyZ\"><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token keyword\" style=\"color:#00009f\">package</span><span class=\"token plain\"> main</span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">import</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:#e3116c\">\"fmt\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:#00009f\">func</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:#d73a49\">main</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:#393A34\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\">  fmt</span><span class=\"token punctuation\" style=\"color:#393A34\">.</span><span class=\"token function\" style=\"color:#d73a49\">Printf</span><span class=\"token punctuation\" style=\"color:#393A34\">(</span><span class=\"token string\" style=\"color:#e3116c\">\"Hello World\\n\"</span><span class=\"token punctuation\" style=\"color:#393A34\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:#393A34\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:#393A34\">}</span><br></div></code></pre></div></div>\n<p>Source: <a href=\"https://helloworldcollection.github.io/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">https://helloworldcollection.github.io</a></p>",
            "url": "https://fahri.blog/posts/hello-world/",
            "title": "Hello World",
            "summary": "Hello World examples in Java, Kotlin, JavaScript, Elixir, and Go.",
            "date_modified": "2017-07-22T09:20:01.000Z",
            "author": {
                "name": "Fahri Nurul Hidayat",
                "url": "https://github.com/fahrinh"
            },
            "tags": []
        }
    ]
}