<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Olivier Guimbal</title>
    <description>The latest articles on DEV Community by Olivier Guimbal (@oguimbal).</description>
    <link>https://dev.to/oguimbal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F236418%2F38691aba-6383-4916-a062-03729757d054.jpg</url>
      <title>DEV Community: Olivier Guimbal</title>
      <link>https://dev.to/oguimbal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oguimbal"/>
    <language>en</language>
    <item>
      <title>Introducing ngx-react : 🅰️Angular + ⚛️React interoperability without pain.</title>
      <dc:creator>Olivier Guimbal</dc:creator>
      <pubDate>Tue, 28 Sep 2021 13:16:45 +0000</pubDate>
      <link>https://dev.to/oguimbal/introducing-ngx-react-angular-react-interoperability-without-pain-23k</link>
      <guid>https://dev.to/oguimbal/introducing-ngx-react-angular-react-interoperability-without-pain-23k</guid>
      <description>&lt;p&gt;Have you ever wanted to use React components in an Angular application ? Or to start migrating an Angular app to React component-by-component ? Or simply use both at the same time ?&lt;/p&gt;

&lt;p&gt;I developped &lt;a href="https://github.com/oguimbal/ngx-react"&gt;ngx-react&lt;/a&gt; which allows you to do just that with ease.&lt;/p&gt;

&lt;p&gt;It enables you to use your Angular components in React, and vice versa, quite transparently, and without boilerplate.&lt;/p&gt;

&lt;h1&gt;
  
  
  📐 Setup
&lt;/h1&gt;

&lt;p&gt;Just declare a bridge, somewhere in your application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NgxReactBridge&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ngx-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bridge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;NgxReactBridge&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// bridge options:&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/** Add a global react provider here */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Use 🅰️ in ⚛️
&lt;/h1&gt;

&lt;p&gt;Then, to use an Angular component in React, just import it like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AsReact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bridge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toReact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyAngularCommonent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// use it 👉  &amp;lt;AsReact prop={whatever} /&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated ⚛️ component will take as props all the &lt;code&gt;@Input()&lt;/code&gt;s of your 🅰️ component, and all the &lt;code&gt;@Output()&lt;/code&gt;s, mapped to functions. (i.e. &lt;code&gt;@Output() onThing: EventEmitter&amp;lt;string&amp;gt;&lt;/code&gt; will be mapped to prop &lt;code&gt;onThing: (event: string) =&amp;gt; void&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Use ⚛️ in 🅰️
&lt;/h1&gt;

&lt;p&gt;To use a React component in Angular, you'll have to do a tiny bit more work... for instance if you have a React component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyReactComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;dataChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// [...]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Then magically convert it to its Angular counterpart like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Directive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-react-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MyReactComponent_Angular&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;reactBridge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toAngular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;MyReactComponent&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// a bit of extra work: You will have to map the properties yourself &lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;dataChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;EventEmitter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(the Angular compiler doesnt allow to build dynamic components... so we have to declare them statically)&lt;/p&gt;

&lt;h1&gt;
  
  
  Services
&lt;/h1&gt;

&lt;p&gt;Just inject Angular services in React like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyAngularService&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Wrapping up
&lt;/h1&gt;

&lt;p&gt;I'll write more about this when I have more time 👉 But please share your thought if you have some :) &lt;/p&gt;

&lt;p&gt;More details on  &lt;a href="https://github.com/oguimbal/ngx-react"&gt;the ngx-react repository&lt;/a&gt; &lt;/p&gt;

</description>
      <category>angular</category>
      <category>react</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Learn functional programing with me - Part 1 : Language choice</title>
      <dc:creator>Olivier Guimbal</dc:creator>
      <pubDate>Tue, 23 Feb 2021 07:56:58 +0000</pubDate>
      <link>https://dev.to/oguimbal/learn-functional-programing-with-me-part-1-language-choice-5bc1</link>
      <guid>https://dev.to/oguimbal/learn-functional-programing-with-me-part-1-language-choice-5bc1</guid>
      <description>&lt;p&gt;So, I've decided to write a blog.&lt;/p&gt;

&lt;p&gt;Sure, I could use one of many solutions out there and setup a blog in minutes, but writing a blog is not the main purpose here (who gives a 💩 about my opinion anyway ?).&lt;br&gt;
I'd like to learn a language AND build something while doing so.&lt;/p&gt;

&lt;p&gt;If you're interested, I'd like this to be collaborative in some way: You could comment my choices, learn from them, and influence them (for instance, you can today influence the language I will use - see below).&lt;/p&gt;



&lt;h1&gt;
  
  
  🤔 Why would you care ?
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;TLDR :&lt;/strong&gt; &lt;em&gt;I will explain, step by step, how I built it, and I will post all the resources that I used to learn how to do it along the way.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In my (relatively) long experience, I learnt and used on real projects many languages that could be qualified as imperative more than functional languages, such as Javascript/Typescript, C#, Dart, Java, VB, C++ (non exhaustive list).&lt;/p&gt;

&lt;p&gt;I've always been toying with FP languages, but never had the oportunity to use them on an actual project, so I've decided to build a blog using one of those.&lt;/p&gt;

&lt;p&gt;If like me, you already know imperative languages, but you're interested by learning a functional language, you might want to stick with this series. &lt;/p&gt;

&lt;p&gt;It aims experienced developpers with at least a little bit of awareness about FP concepts.&lt;/p&gt;

&lt;p&gt;Being myself a semi-begginer in most FP languages, you will probably learn the language progressively with me, see (and discuss?) my architectual choices, my mistakes, my misunderstandings, and the solutions I came up with.&lt;/p&gt;



&lt;h1&gt;
  
  
  🤪 Why do I do that ?
&lt;/h1&gt;

&lt;p&gt;My goal here is to write a tutorial which is progressive, and hands on.&lt;/p&gt;

&lt;p&gt;I'm tired of reading hundreds of attempts of guys who already got it to teach category theory by the menu, because they think that their approach at teaching it is better. Reading those, I've been admitedly learning a lot, but I feel incapable of building an actual project with all that knowledge. Which seems retrospectively crazy to me... I don't recall having this kind of feeling when learning simple non FP languages.&lt;/p&gt;

&lt;p&gt;When it comes to learning, I believe practice is better that theory to begin with, and that learning practice &lt;strong&gt;with&lt;/strong&gt; someone is better that learning it &lt;strong&gt;from&lt;/strong&gt; someone. Even if it means not learning things the academic way.&lt;/p&gt;



&lt;h1&gt;
  
  
  🎯 Specifications - what should it do ?
&lt;/h1&gt;

&lt;p&gt;Here is what I'm expecting it to do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To be server-side rendered (for SEO) - so no client-only/SPA stuff.&lt;/li&gt;
&lt;li&gt;To be serverless, and to be served via a CDN, zero fixed cost (if possible via &lt;a href="https://workers.cloudflare.com/" rel="noopener noreferrer"&gt;Cloudflare Workers&lt;/a&gt;, because I 💖 them.. if not, via some kind of &lt;a href="https://aws.amazon.com/lambda/edge/" rel="noopener noreferrer"&gt;Lambda@Edge&lt;/a&gt; or equivalent, or even some kind of FAAS + github pages... why not ?)&lt;/li&gt;
&lt;li&gt;To have a git repository containing .md files as raw source (I don't want any online editor, authentication system, or other 💩) - will probably be implemented using hooks/github actions which will update the actual blog.&lt;/li&gt;
&lt;li&gt;To have multiple blogging categories  (tech, opinions, ...), presented as columns on the landing page.&lt;/li&gt;
&lt;li&gt;To support multiple formats: tweet-like, pictures, videos, articles (to begin with)&lt;/li&gt;
&lt;li&gt;To automatically repost articles I'm writing on various medium  (dev.to, medium.com, reddit, twitter, mastodon, ...), and if legally and technically possible, show the associated comments/likes/claps/retweets/etc on the main blog.&lt;/li&gt;
&lt;li&gt;To be written using FP language(s)&lt;/li&gt;
&lt;/ul&gt;



&lt;h1&gt;
  
  
  👅 Language
&lt;/h1&gt;

&lt;p&gt;So, I must say, I've toyed a lot with FP languages, thinking that at one point, one of those might strike me as "the best for my needs". That did not happen. Instead, I got lost along the way, learning a little bit about each one, but never mastering any.&lt;/p&gt;

&lt;p&gt;Here is a non exhaustive list of the languages that I considered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1️⃣ Purescript&lt;/li&gt;
&lt;li&gt;2️⃣ ELM&lt;/li&gt;
&lt;li&gt;3️⃣ ReasonML/ReScript&lt;/li&gt;
&lt;li&gt;4️⃣ Haskell&lt;/li&gt;
&lt;li&gt;5️⃣ Clojure(Script)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Below is my perception about each one of those.&lt;/p&gt;

&lt;p&gt;As of writing this article, my curiosity about Haskell or equivalent would make me choose Purescript (I'm not settled on the UI lib to use).&lt;/p&gt;

&lt;p&gt;If you'd rather see me write it in another of those languages, please comment, I might (or might not) be convinced or influenced , and take your choice into account 😊&lt;/p&gt;

&lt;h2&gt;
  
  
  1️⃣ Purescript
&lt;/h2&gt;

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

&lt;p&gt;Purescript is a child of Haskell (their syntax are almost identical), targeting mostly Javascript.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ PROS:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pure FP&lt;/strong&gt; Purescript is a pure functional language. This seems to bring a lot of liberties and guarantees while reasoning about your code.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interop:&lt;/strong&gt; It outputs quite readable Javascript, and has a very clean &lt;a href="https://en.wikipedia.org/wiki/Foreign_function_interface" rel="noopener noreferrer"&gt;FFI&lt;/a&gt; (meaning that you can interact with existing Js code/libraries very easily).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client+Server:&lt;/strong&gt;It is usage agnostic, meaning that it can be used both server-side (running NodeJS), and client-side&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Typing:&lt;/strong&gt; I've only explored a bit of them, but Haskell-like type systems seems soo smooth, and leads to elegant implementations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  💥 CONS:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learning curve:&lt;/strong&gt; This is no little thing, it is a "next-level" programming language. Meaning that the concepts that you can play with are so much more powerful and advanced that your brain will hurt by learning it. A single line of code can hide much more meaning compared to a classic language, which always make you wonder if you got it all, when reading code. Seems to worth it, though.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📚 Framework:
&lt;/h3&gt;

&lt;p&gt;My first exploratory work would point at either &lt;a href="https://pursuit.purescript.org/packages/purescript-halogen/5.0.0" rel="noopener noreferrer"&gt;purescript-halogen&lt;/a&gt; or &lt;a href="https://pursuit.purescript.org/packages/purescript-elmish/0.3.2" rel="noopener noreferrer"&gt;purescript-elmish&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Halogen seems nice and widely used, but its SSR story is &lt;a href="https://github.com/srghma/purescript-halogen-nextjs" rel="noopener noreferrer"&gt;less clear&lt;/a&gt;. On the other hand, Elmish has the advantage of kind-of learning Elm along the way, but is less used (then, there will be less learning resource).&lt;/p&gt;

&lt;h2&gt;
  
  
  2️⃣ ELM
&lt;/h2&gt;

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

&lt;p&gt;Like Purescript, Elm is also a child of Haskell, but much more simpler. It actually feels like a simplification + specialization of Haskell, bringing more guarantees on the table, along with a much more nicer syntax error messages.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ PROS:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pure FP&lt;/strong&gt; ELM is also a pure functional language.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety:&lt;/strong&gt; ELM proudly guarantees near-zero runtime exceptions. Meaning that it is literally impossible to encounter any runtime error with ELM (except inevitable things such as out-of-memory &amp;amp; stack-overflow errors). It obviously does not imply that you cannot write errors in your logic, but it means that if it compiles, it will not crash.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error messages:&lt;/strong&gt; ELM is very well known to have state-of-the art syntax error messages. They seem useful, pointing at solutions/suggestions/useful links.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bundle sizes&lt;/strong&gt; ELM seems to crush every other language/framework when it comes to bundle size. ELM bundles seems to casually weight about an order of magnitude less than other tech typical bundle sizes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relatively widespread:&lt;/strong&gt; Compared to the other languages I considered, I think ELM is the most used to build frontends (it still remains a fringe comunity, though)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relatively easy to learn&lt;/strong&gt; Its ecosystem is very simple... there is often only one way of doing things, and its syntax is straightforward... that makes it easy to learn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coherent ecosystem&lt;/strong&gt; The community around ELM seems helpful, not flawed by the dissentions I seem to have percieved in other communities, and its package system is rock solid (it enforces semver to published libraries, ensuring nothing will ever break)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  💥 CONS:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No SSR&lt;/strong&gt; - That is not a small one... ELM cannot do SSR + Hydration. Meaning that we will have to choose between server side rendering and interactivity. I think I would have chosen ELM no question asked if it did suport SSR. But I'm not trying to build a SPA :(&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interop&lt;/strong&gt; - As neat as the dev experience is using ELM, it is quite bad when it comes with interacting with JS. You have to communicate through &lt;a href="https://guide.elm-lang.org/interop/ports.html" rel="noopener noreferrer"&gt;ports&lt;/a&gt;, which are quite rigid and tedious. You'll also have much trouble on basic things when it comes to speaking non-elmish, like when deserializing JSON coming from an AJAX query (If i'm correct, you'll systematically have to implement explicit ad-hoc JSON decoders 😑).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📚 Framework:
&lt;/h3&gt;

&lt;p&gt;Not relevant :) ELM is its own framework !&lt;/p&gt;

&lt;p&gt;That said, &lt;a href="https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/" rel="noopener noreferrer"&gt;elm-ui&lt;/a&gt; seems quite interesting as a library. I think I would use it&lt;/p&gt;

&lt;h2&gt;
  
  
  3️⃣ ReasonML/ReScript
&lt;/h2&gt;

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

&lt;p&gt;It is an OCaml descendent.&lt;br&gt;
It seems to put an accent on interoperability with JS, and pragmatism. But I don't know much about it except the basic syntax.&lt;/p&gt;

&lt;p&gt;So any feedback is welcome.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ PROS:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;More familiar:&lt;/strong&gt; While you could not guess what random code from the previous two languages is doing without any initiation to their syntax, Reason feels more familiar. It "looks like" something you would understand if you already know languages which are not considered as purely functional, but have some affinity with the functional style, such as Scala, Rust, Kotlin... and even JS.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  💥 CONS:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Messy ecosystem:&lt;/strong&gt; Sooo... well... It takes at least half an hour to understand that Reason, ReasonML, ReScript, Bucklescript, and all that are actually kind of the same thing, I guess, but not really, but they're not anymore, but they are transitioning, but ... wait &lt;a href="https://www.destroyallsoftware.com/talks/wat" rel="noopener noreferrer"&gt;wat ?&lt;/a&gt; Couldnt someone tell me why all the fuss ? Couldnt we have one way to go ? And how am I sure I'm not starting to use a version that will lead me to a dead-end ?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📚 Framework:
&lt;/h3&gt;

&lt;p&gt;Like I said, I don't know enough about it, but &lt;a href="https://reasonml.github.io/reason-react/" rel="noopener noreferrer"&gt;reasonreact&lt;/a&gt; seems to be the way to go ! Any feedback appreciated&lt;/p&gt;

&lt;h2&gt;
  
  
  4️⃣ Haskell
&lt;/h2&gt;

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

&lt;p&gt;The father of all languages. Over the decades, Haskell has never exploded in popuplarity, but it has inspired in one way or another most of the typed languages out there.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ PROS:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Syntax &amp;amp; type system:&lt;/strong&gt; Same as purescript... Haskell feels and is very powerful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; Not really something that is useful when chosing a language to write a blog, but Haskell can compare to C++ in terms of performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  💥 CONS:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server only:&lt;/strong&gt; There is no efficient way to use Haskell client-side. Weirdly enought, we'll face the same dilemma as with ELM (which is client-only).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning curve:&lt;/strong&gt; Same as purescripts...&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Somehow weird ecosystem&lt;/strong&gt;: I wrote about it &lt;a href="https://dev.to/oguimbal/haskell-as-a-first-timer-am-i-missing-something-or-is-something-broken-19hb"&gt;here&lt;/a&gt;, but Haskell has been out there for a very long time... meaning that you never know when a resource is relevant, abandoned, ...&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📚 Framework:
&lt;/h3&gt;

&lt;p&gt;Given that Haskell is only running server-side, and given the "serverless" constraint, using Haskell with widespread frameworks to develop websites such as &lt;a href="https://www.yesodweb.com/" rel="noopener noreferrer"&gt;yesod&lt;/a&gt; seems out of the question. If using Haskell, I would have to write some kind of lambda which generates a fully static website. After a bit of research, it would seem that an aws lambda running &lt;a href="https://github.com/theam/aws-lambda-haskell-runtime" rel="noopener noreferrer"&gt;aws-lambda-haskell-runtime&lt;/a&gt; should be a good match.&lt;/p&gt;

&lt;h2&gt;
  
  
  5️⃣ Clojure(Script)
&lt;/h2&gt;

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

&lt;p&gt;Clojure (or Clojurescript if you want to compile to JS) is a Lisp language.&lt;/p&gt;

&lt;p&gt;I included it here because I used to play a bit with Clojurescript a while ago, and I found it quite original, but I wont dive into details here, since I find it too diferent to be compared with the other 4:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is is a fully dynamic language, no typing (there is &lt;a href="https://clojure.org/guides/spec" rel="noopener noreferrer"&gt;spec&lt;/a&gt;, though)&lt;/li&gt;
&lt;li&gt;Like all Lisps, it does not have a syntax, per se. It's only parenthesis 🤪&lt;/li&gt;
&lt;li&gt;Is is quite flexible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;... but I have not investigated weather if SSR is easy, nor about its deployability on a FAAS platform (that said, it runs on the JVM, so it should be the same as Java), cold-start times, etc... and I'd prefer using a typed language. So I'd need a lot of convincing to go with that one ! (even if I like it to play, learn, and write prototypes)&lt;/p&gt;



&lt;h1&gt;
  
  
  👋 Conclusion
&lt;/h1&gt;

&lt;p&gt;Okay, that was long. So I have questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What do you think ? &lt;/li&gt;
&lt;li&gt;Would you have something to add or to correct ? &lt;/li&gt;
&lt;li&gt;Would you be interested in following such a series ? &lt;/li&gt;
&lt;li&gt;Which language interests you the most ? &lt;/li&gt;
&lt;li&gt;Have I forgotten a FP language that you love and would like to be considered ? &lt;/li&gt;
&lt;li&gt;Which kind of supporting tech (lambda, cloudflare workers, azure functions, github actions, ...) ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this interests some, I will post articles &amp;amp; thoughts as I develop this blog. Otherwise, well... I guess that will remain a private journey !&lt;/p&gt;

&lt;p&gt;Thanks for reading, and stay tuned for the follow-up !&lt;/p&gt;

</description>
      <category>functional</category>
      <category>productivity</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Haskell as a first timer - Am I missing something ?</title>
      <dc:creator>Olivier Guimbal</dc:creator>
      <pubDate>Wed, 03 Feb 2021 08:59:50 +0000</pubDate>
      <link>https://dev.to/oguimbal/haskell-as-a-first-timer-am-i-missing-something-or-is-something-broken-19hb</link>
      <guid>https://dev.to/oguimbal/haskell-as-a-first-timer-am-i-missing-something-or-is-something-broken-19hb</guid>
      <description>&lt;center&gt;
&lt;br&gt;
&lt;em&gt;NB: This is also commented &lt;a href="https://www.reddit.com/r/haskell/comments/lbk51h/haskell_as_a_first_timer_am_i_missing_something/"&gt;on reddit&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
&lt;/center&gt;
&lt;br&gt;


&lt;p&gt;So... I've been toying a lot with Haskell lately.&lt;/p&gt;

&lt;p&gt;But I feel a bit schizophrenic about my first impressions. There &lt;br&gt;
 is something both very right, and very wrong about it.&lt;/p&gt;

&lt;p&gt;While addressing most of my top concerns about other languages, and giving me hope to discover a language that I could love, the Haskell ecosystem seems in the meantime broken where I expected it the least to be. It is sooo frustrating, and leaves a bitter taste of unachievement :(&lt;/p&gt;

&lt;p&gt;Have I missed a crucial step ? Or is there really something broken in its ecosystem ? (may it be a victim of its age × lack of wide adoption ?)&lt;/p&gt;

&lt;p&gt;Let me elaborate a bit.&lt;/p&gt;

&lt;h1&gt;
  
  
  💖 First looks - The (very) good parts
&lt;/h1&gt;

&lt;p&gt;I wont dive into details, since this is widely documented, but in short, I loved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Its world-class type system 😱 so smooth.&lt;/li&gt;
&lt;li&gt;Immutablility, Pure FP, all that good stuff.&lt;/li&gt;
&lt;li&gt;Its syntax. Not the most beginner friendly, but if feels smart and concise when you get it. Other languages then tend to feel verbose.&lt;/li&gt;
&lt;li&gt;That it looks like maths&lt;/li&gt;
&lt;li&gt;The simplifications the compiler hints at&lt;/li&gt;
&lt;li&gt;The depth of this language. I only got a glimpse of its abstraction power, and it is definitely not playing in the same league as others. It is so exciting not to feel that a compiler is forcing you to write dumb things just because language designers felt like "this" or "that" abstraction was not part of the language.&lt;/li&gt;
&lt;li&gt;TDD as in Type-Driven-Development 😁 If you've ever searched for a type signature on &lt;a href="https://hoogle.haskell.org/"&gt;Hoogle&lt;/a&gt;, you'll &lt;a href="https://hoogle.haskell.org/?hoogle=Ord%20b%20%20%3D%3E%20(a%20-%3E%20b)%20-%3E%20%20%5Ba%5D%20-%3E%20a"&gt;get what I mean&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Great learning resources such as &lt;a href="http://learnyouahaskell.com/chapters"&gt;learn you a haskell&lt;/a&gt; or &lt;a href="https://www.fpcomplete.com/haskell/learn/"&gt;fp complete&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get the picture, I think that Haskell in itself is neat. But seriously, WTF is wrong with its ecosystem ?&lt;br&gt;
Once you're done toying, and start to get like "okay, now lets do real world shit", everything seems to fall apart.&lt;/p&gt;

&lt;h1&gt;
  
  
  🥪 Frustration 1 - Stack configuration
&lt;/h1&gt;

&lt;p&gt;If I understood right, &lt;a href="https://docs.haskellstack.org/"&gt;stack&lt;/a&gt; was supposed to bring to Haskell a decent all-inclusive CLI equivalent to those that you have with Dotnet, Deno, Elm, and whatnot. &lt;br&gt;
Okay. It kind of seems to be (or at least a huge improvement over not having it).&lt;/p&gt;

&lt;p&gt;But when npm and friends set a standard of having one file which defines your package (dependencies, and such), why deviate from it introducing &lt;code&gt;package.yaml&lt;/code&gt; and &lt;code&gt;stack.yaml&lt;/code&gt; ? How the f*** am I supposed to guess that I must &lt;a href="https://docs.haskellstack.org/en/stable/GUIDE/#extra-deps"&gt;read a random part&lt;/a&gt; of the Stack documentation to understand that yea, you can install packages by adding them in &lt;code&gt;package.yaml&lt;/code&gt;, but for some of them, you must also add them in &lt;code&gt;stack.yaml&lt;/code&gt; ... wait ... what ??! Okay, it makes kinda sense once you know why, but why not stick to the "expected" way to go by default ?&lt;/p&gt;

&lt;p&gt;When learning a new language or framework, I usually spend minutes trying to understand how the associated CLI &amp;amp; package manager works. I had to spend frustrating &lt;strong&gt;hours&lt;/strong&gt; on stack to understand that it just dont work as others do. What's even more confusing is that it &lt;strong&gt;almost&lt;/strong&gt; does ! Why not ? And why not a "stack install xxx" command which writes yaml files ? &lt;/p&gt;

&lt;h1&gt;
  
  
  💥 Frustration 2 - Stack error messages
&lt;/h1&gt;

&lt;p&gt;Is it just me ? Or does installing a library though stack is just like playing russian roulette ?&lt;/p&gt;

&lt;p&gt;I think everyone who's been a solo Haskell learner might at one point or another felt that sentiment of hoplessness, despair, and self doubt when Haskell tooling just keeps throwing at you thousands of giberrish error lines for no appearant reason, just because you tried to install a package or such (especially if you're already mastering several other ecosystems which behave "as you would expect")&lt;/p&gt;

&lt;p&gt;For instance, how the hell am I supposed to make sense of &lt;a href="https://gist.github.com/oguimbal/0ef39d890eed2328b8f5f9d619fc324e#file-dev-to-stack-persistent-install-errlog-L122-L124"&gt;this kind of error logs&lt;/a&gt; without getting a headache reading usless stuff ? (for the record, I just added a very widely used package to package.yaml... nothing fancy !)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I would expect Stack not to  tell me "please scroll up an unkown number of lines to find the error yourself". Especially since there are a lot of things that look like errors between me and the actual error. I guess one can get used to it, but if the point of a nice build tool isnt to help you, what is ?&lt;/li&gt;
&lt;li&gt;I would expect the luxry of a colorized console output, somehow ?&lt;/li&gt;
&lt;li&gt;The actual error does not even mention the word "error" 😩 Pretty hard to find the error by yourself when you dont know what you're looking for.&lt;/li&gt;
&lt;li&gt;If a native dependency is required, isnt it the toolchains' job to abstract that away, and to install it, or at least tell me how to install it (hint: for my error, I guess that a 600MB &lt;code&gt;apt-get install pg&lt;/code&gt; is not the answer)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of the significant libraries I tried just failed miserably to install for one reason or another. Which leads me to my second frustration.&lt;/p&gt;

&lt;h1&gt;
  
  
  🤼 Frustration 3 - Maintainers ?
&lt;/h1&gt;

&lt;p&gt;Is it just me ? Or most packages are just abandonned, even sometimes left in a state that is no longer compatible with newer versions of the GHC, with nobody left to answer 3 years old issues and pull requests ?&lt;/p&gt;

&lt;p&gt;I am definitely okay (even a bit excited by) trying to adhere to a fringe ecosystem. I dont need millions of downloads to feel safe about a piece of code I'm using. But I fear dead communities, and it has been a bit puzzling to see how inactive most of the repos I encountered are... &lt;/p&gt;

&lt;p&gt;Dont get me wrong: I am &lt;a href="https://github.com/oguimbal/pg-mem"&gt;trying to contribute to opensource as well&lt;/a&gt;, so I get that supporting small projects can be demanding. There's nothing wrong in not spending your weekends on OS. But not asking for help, nor specifying that a project is unmaintained, nor even answering issues &amp;amp; pull requests for years feels just wrong.&lt;/p&gt;

&lt;p&gt;nb: I dont think too much finger pointing will solve anything, so I wont name any specific library, but you dont have to search very long to find such libs on hackage.&lt;/p&gt;

&lt;h1&gt;
  
  
  📚 Frustration 4 - Documentawhat ?
&lt;/h1&gt;

&lt;p&gt;I wont moann too much about it because I'm definitely not the first one to point that out.&lt;/p&gt;

&lt;p&gt;I get that the holly Types are enough. I get that. But I could argue that even if you could theorically learn gibberish  by reading a dictionary on a smartwatch, its usually more pleasant to read, watch or listen to actual people, producing actual sentences.&lt;/p&gt;

&lt;p&gt;I dont understand. When you're willing to sacrifice your time to opensource... Why not writing 10 lines targetting mere mortals willing to use your code to tell the general idea behind your work ? Not doing so just feels a bit like "go fuck yourself &amp;amp; read the types, you dumb monkeys" 😯&lt;/p&gt;

&lt;h1&gt;
  
  
  👉 Conclusion - Please enlighten me
&lt;/h1&gt;

&lt;p&gt;That's where I stand. I am very excited by Haskell, while really puzzled to find myself not willing to try to write actual production stuff with it, for absurd reasons.&lt;/p&gt;

&lt;p&gt;These are just small glitches, in the sense that they feel just like superficial flaws, which have been overcome in almost all decent language communities... but they are crippling enough to me so I dont see how I could not have problems working with Haskell.&lt;/p&gt;

&lt;p&gt;Still, I will continue to fiddle around with this awesome language, but I gave up my short term plans to build something real with it.&lt;/p&gt;

&lt;p&gt;But I'm very open to someone willing to change my mind... What do you think ? Is Haskell dying, or in a status quo, being okay mid distance from a research language to a widely adoptable &amp;amp; production ready thing ? Or is it still a passionate community it seems to have been ? Are those flaws a temporary thing, or the symptoms of something rotten ? Have you had recent production successes with Haskell ? What's your reciepe to onboard people ? How do you see the future for Haskell ? What do you think of Purescript ?&lt;/p&gt;

&lt;p&gt;ps: Sorry if my English is off, I'm french :)&lt;/p&gt;

</description>
      <category>haskell</category>
      <category>functional</category>
    </item>
    <item>
      <title>My favorite pages on the whole internet</title>
      <dc:creator>Olivier Guimbal</dc:creator>
      <pubDate>Sat, 28 Nov 2020 15:16:41 +0000</pubDate>
      <link>https://dev.to/oguimbal/my-favorite-pages-on-the-whole-internet-4mpb</link>
      <guid>https://dev.to/oguimbal/my-favorite-pages-on-the-whole-internet-4mpb</guid>
      <description>&lt;p&gt;I know it has little value to just dump links like that, but those have made me laugh so hard each time I visited them that I feel compeled to share them, in case you dont know them !&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.destroyallsoftware.com/talks/wat" rel="noopener noreferrer"&gt;WAT ? talk&lt;/a&gt;  is by far my favorite. I Listened to it millions of times. Still funny.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Learn &lt;a href="https://www.youtube.com/watch?v=jbwO1DYgsFY" rel="noopener noreferrer"&gt;why unit testing is important&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get some &lt;a href="https://stackoverflow.com/questions/184618/what-is-the-best-comment-in-source-code-you-have-ever-encountered" rel="noopener noreferrer"&gt;inspiration here&lt;/a&gt; for your comments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Have &lt;a href="https://shouldideploy.today/" rel="noopener noreferrer"&gt;a wise advice&lt;/a&gt; before deploying in production&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be aware that &lt;a href="https://xkcd.com/552/" rel="noopener noreferrer"&gt;correlation&lt;/a&gt; does not imply &lt;a href="http://www.tylervigen.com/spurious-correlations" rel="noopener noreferrer"&gt;causation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I sometimes find myself not liking XKCD... &lt;a href="https://xkcd.com/683/" rel="noopener noreferrer"&gt;then&lt;/a&gt; &lt;a href="https://xkcd.com/323/" rel="noopener noreferrer"&gt;I&lt;/a&gt; &lt;a href="https://xkcd.com/303/" rel="noopener noreferrer"&gt;remember&lt;/a&gt; &lt;a href="https://xkcd.com/2236/" rel="noopener noreferrer"&gt;these&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.defprogramming.com/" rel="noopener noreferrer"&gt;Some&lt;/a&gt; &lt;a href="https://uhmmm.app/" rel="noopener noreferrer"&gt;less&lt;/a&gt; &lt;a href="https://developer.android.com/reference/android/util/Log.html#wtf(java.lang.String,%20java.lang.String)" rel="noopener noreferrer"&gt;funny&lt;/a&gt; &lt;a href="https://developer.android.com/reference/android/app/ActivityManager#isUserAMonkey()" rel="noopener noreferrer"&gt;links&lt;/a&gt; &lt;a href="https://developer.android.com/reference/android/os/UserManager#isUserAGoat()" rel="noopener noreferrer"&gt;but&lt;/a&gt; &lt;a href="https://dorey.github.io/JavaScript-Equality-Table/" rel="noopener noreferrer"&gt;still&lt;/a&gt; worth a click&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fczge2jq3nt962e56dwax.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fczge2jq3nt962e56dwax.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxeg5jid0iqptjjui2vly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxeg5jid0iqptjjui2vly.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dont hesitate to share yours ! &lt;/p&gt;

&lt;p&gt;(and check out &lt;a href="https://github.com/oguimbal/pg-mem" rel="noopener noreferrer"&gt;the lib I recently published&lt;/a&gt; if you have some time to spare !)&lt;/p&gt;

</description>
      <category>jokes</category>
      <category>discuss</category>
    </item>
    <item>
      <title>localStorage vs cookies: the "tabs vs spaces" sterile debate of web development 🙄</title>
      <dc:creator>Olivier Guimbal</dc:creator>
      <pubDate>Wed, 25 Nov 2020 09:32:24 +0000</pubDate>
      <link>https://dev.to/oguimbal/localstorage-vs-cookies-the-tabs-vs-spaces-sterile-debate-of-web-development-h36</link>
      <guid>https://dev.to/oguimbal/localstorage-vs-cookies-the-tabs-vs-spaces-sterile-debate-of-web-development-h36</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;EDIT: The title not being clear enough (I thought it was implicit): This article is about the "&lt;strong&gt;storing tokens&lt;/strong&gt; in localStorage or in cookies for &lt;strong&gt;SPA&lt;/strong&gt;s" debate. It is &lt;strong&gt;NOT&lt;/strong&gt; about using cookies to store general purpose data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm a tad tired of reading "dont use localStorage, it's not secure". Why ? Oh, yes "its accessible in JS". Let me tell you how this seems to be an overrated argument to me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://xkcd.com/386/" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyr9a9rszbmarrmk7u20q.png" alt="duty calls"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  If someone owns you, someone owns you.
&lt;/h1&gt;

&lt;p&gt;If someone can run arbitrary JS on your website, do you really believe a peremptible JWT will necessarily be the only thing that can be exploitable ?&lt;/p&gt;

&lt;p&gt;Personally, I'd go with something far more interesting to me: &lt;strong&gt;Collecting what user are typing in password boxes&lt;/strong&gt;. Or just performing the requests that interest me directly from their browser. Those exploits are even easier to write when using cookies, given that you dont have to guess where is the token stored nor how to use it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Cookies also have their drawbacks
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Protecting against CSRF is not that easy, and beginners are not even aware of it.&lt;/li&gt;
&lt;li&gt;Implementation of multiple authentication is harder (if you're writing a signle API that must be usable in multiple websites)&lt;/li&gt;
&lt;li&gt;You cant control them (easily tell if you're logged-in, read associated data, ...)&lt;/li&gt;
&lt;li&gt;CORS is harder with them.&lt;/li&gt;
&lt;li&gt;etc...&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  XSS / Malicious JS dependencies: The easy fix.
&lt;/h1&gt;

&lt;p&gt;You're worried that one of your dependencies might be accessing your localStorage maliciously ?&lt;/p&gt;

&lt;p&gt;Well, that's not a strong valid argument, you could just prevent it to do so like that when bootstraping your application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voilà ! There is no more localStorage exposed in your window, but you still can access your tokens via the "storage" local variable (of course, you must keep it in a private scope).&lt;/p&gt;

&lt;p&gt;These two lines of code will protect you from the most obvious and common exploit that localStorage is blamed for.&lt;/p&gt;

&lt;p&gt;(of course you could imagine spying tokens by overriding fetch or equivalent, but that also is mitigable... its about preventing 99% of exploits, this is not strong security) &lt;/p&gt;

&lt;p&gt;If other parts of your app need to access local storage, you could set &lt;code&gt;window.localStorage&lt;/code&gt; to a proxy that only lets the user access non critical parts of your local storage, leaving your precious tokens out of their sight.&lt;/p&gt;

&lt;h1&gt;
  
  
  Which one to use then ?
&lt;/h1&gt;

&lt;p&gt;I think that the web has more suffered (and is still suffering) from CSRF attacks compared to stolen JWTs, so dont tell me that https cookies are the secure way to go. Unless you're writing ultra-secure and highly-reviewed code, no, they're not. Its easier to make mistakes with cookies compared with localStorage tokens.&lt;/p&gt;

&lt;p&gt;Just to be clear: I dont prefer one over another... I'm just saying that this debate is a bit useless, both approaches having their own sweetspots and weakspots.&lt;/p&gt;

&lt;p&gt;I'm just sick of people explaining you otherwise with a condescending tone just because they think they've understood all there is to know by saying "its accessible by JS". Or because they've read somewhere that localStorage tokens might be considered as a potential security leak by some. Give me a break. The world is about nuance, not about dogmas.&lt;/p&gt;

&lt;p&gt;Happy to hear what you think of this in the comments.&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Zero delay development &amp; unit testing iterations</title>
      <dc:creator>Olivier Guimbal</dc:creator>
      <pubDate>Tue, 06 Oct 2020 06:51:23 +0000</pubDate>
      <link>https://dev.to/oguimbal/zero-delay-development-unit-testing-iterations-1jk7</link>
      <guid>https://dev.to/oguimbal/zero-delay-development-unit-testing-iterations-1jk7</guid>
      <description>&lt;p&gt;If you write js or ts targeting node, and would like to improve your daily life and your productivity, yey 🎉 this article is for you !&lt;/p&gt;

&lt;h1&gt;
  
  
  TLDR
&lt;/h1&gt;

&lt;p&gt;As devs, our daily life is often a constant back and forth between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writing code&lt;/li&gt;
&lt;li&gt;Running unit tests&lt;/li&gt;
&lt;li&gt;Running the written code "for real"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may have noticed how joyful it is when this iteration process is fast enough so you can have this instant feedback loop between writing and testing.&lt;/p&gt;

&lt;p&gt;This article explains how to leverage Webpack HMR in order to get instant restart/reload/run for your NodeJS server and your Mocha unit tests, whatever your codebase size.&lt;/p&gt;

&lt;p&gt;To get a glimpse of what I'm talking about, you can &lt;a href="https://github.com/oguimbal/pg-mem#development"&gt;clone this repo&lt;/a&gt; and follow "Development" instructions (by the way this is a small OS lib I maintain, &lt;a href="https://dev.to/oguimbal/how-to-really-unit-test-code-that-uses-a-db-3gmg"&gt;I wrote about it here&lt;/a&gt;)&lt;/p&gt;

&lt;h1&gt;
  
  
  What is HMR, and how can it be useful ?
&lt;/h1&gt;

&lt;p&gt;If your project is big enough, you probably experience painful delays... when you save a line of code, It might takes ages (or at least seconds) to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reload your unit tests and/or rerun them&lt;/li&gt;
&lt;li&gt;restart your localhost server in order to test this line of code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is because in either case, your whole codebase must be reinterpreted by node (and possibly retranspiled if you use Typescript with ts-node), &lt;strong&gt;including all your node_module dependencies&lt;/strong&gt;. That is &lt;strong&gt;A LOT&lt;/strong&gt; of code to reparse and reexecute for a single line of code changed.&lt;/p&gt;

&lt;p&gt;That is where HMR (Hot-Module-Reload) come in handy.&lt;br&gt;
I wont go into the details of it (Google is your friend), but in two words, the idea is to keep your server running, and only reload the modules that have changed when you save a code file. No need to restart your localhost sever anymore when writing simple changes.&lt;/p&gt;
&lt;h1&gt;
  
  
  Neat. How do I setup HMR ?
&lt;/h1&gt;

&lt;p&gt;Webpack is a good way to do this.&lt;br&gt;
It is often seen as a client-side devtool to bundle webapps, but It can also be used to bundle nodejs apps.&lt;/p&gt;

&lt;p&gt;In short, you'll have to setup webpack for your nodejs server, enabling HMR. To do this, I can point you at &lt;a href="https://github.com/oguimbal/vscode-mocha-hmr-sample"&gt;this sample repo&lt;/a&gt;. It demonstrates how to setup a simple Typescript+Express server with Webpack HMR + unit testing (read its instructions before cloning).&lt;/p&gt;

&lt;p&gt;Here is what happens when you change a line of code when changing your server code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FtYQpS15--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1isaxvput6q68i4t5qab.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FtYQpS15--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1isaxvput6q68i4t5qab.gif" alt="server hmr" width="880" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It just reloaded the changed file (&lt;code&gt;main.ts&lt;/code&gt;), but all its dependencies are already in-memory. If you have hundreds of dependencies, and thousands of code files, your new server will be up and running again waaaay faster using this method.&lt;/p&gt;

&lt;p&gt;To understand the black magic behind it, check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/oguimbal/vscode-mocha-hmr-sample/blob/master/webpack.config.js"&gt;webpack.config.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The end of &lt;a href="https://github.com/oguimbal/vscode-mocha-hmr-sample/blob/575c847880ba96638738b141d8d4af3a467eb28c/src/main.ts#L16"&gt;main.ts&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oguimbal/vscode-mocha-hmr-sample/blob/master/.vscode/launch.json"&gt;.vscode/launch.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The Webpack documentation &lt;a href="https://webpack.js.org/concepts/hot-module-replacement/"&gt;about HMR&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although it is not that complicated, be aware of the fact that HMR is not pure magic. Try to understand how it works behind the hood, and you'll undersand its constraints (which are mainly due to the fact that the modules that are not reloaded may have static in-memory state which will be persisted between HMR recompilations).&lt;/p&gt;
&lt;h1&gt;
  
  
  Also make my unit tests fast again, please
&lt;/h1&gt;

&lt;p&gt;If you are serious about developing NodeJS projects (or any kind of project for that matter), you probably write unit tests.&lt;/p&gt;

&lt;p&gt;If you use vscode as an IDE, and Mocha as your unit test framework, you may already use &lt;a href="https://marketplace.visualstudio.com/items?itemName=hbenl.vscode-mocha-test-adapter"&gt;mocha test explorer + mocha&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In that case, you're lucky 🎉 It so happens that &lt;a href="https://marketplace.visualstudio.com/items?itemName=oguimbal.vscode-mocha-test-adapter"&gt;I forked the official mocha test adapter&lt;/a&gt; to bring HMR support to your unit tests.&lt;/p&gt;

&lt;p&gt;We've been using it for a year in my company, it works quite well, and it is stable - do not hesitate to write an issue &lt;a href="https://github.com/oguimbal/vscode-mocha-test-adapter"&gt;here&lt;/a&gt; if you have any trouble.&lt;br&gt;
It brung the delay between hitting the ▶ button of a unit test and actually hitting a 🔴 breakpoint from 20 seconds to 0.5 sec 🤯.&lt;/p&gt;

&lt;p&gt;Here is how it feels to run a thousand unit tests with it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--itmfJtdq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ir4x0ovtlsfgux9c6xmq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--itmfJtdq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ir4x0ovtlsfgux9c6xmq.gif" alt="run tests" width="880" height="1701"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or to debug one:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jVxcOPmK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m0why76ncb8vjjzjbgae.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jVxcOPmK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m0why76ncb8vjjzjbgae.gif" alt="debug test" width="880" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;... And the good news is: It is that fast even if your codebase has millions of lines of code, thousands of dependencies, and you wont experience any delay when changing a line of code ❤&lt;/p&gt;
&lt;h2&gt;
  
  
  To set it up
&lt;/h2&gt;

&lt;p&gt;If you carefully read &lt;a href="https://github.com/oguimbal/vscode-mocha-hmr-sample"&gt;the aforementioned sample repository&lt;/a&gt;, you might have noticed that it also defines an HMR ready unit testing configuration.&lt;/p&gt;

&lt;p&gt;In short, it involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a simple unit test entry point file that will reference all your unit test files (using context.require)&lt;/li&gt;
&lt;li&gt;Creating a webpack bundle which uses this entry file&lt;/li&gt;
&lt;li&gt;Telling mocha-test-adapter to use the bulit bundle as an HMR bundle &lt;a href="https://github.com/oguimbal/vscode-mocha-hmr-sample/blob/master/.vscode/settings.json"&gt;via .vscode/config.js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Running the webpack bundler (npm start), then reloading all your tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read the instructions of this repo, it should work out of the box !&lt;/p&gt;
&lt;h1&gt;
  
  
  A tip to yet improve your iteration loop experience
&lt;/h1&gt;

&lt;p&gt;Running a test should now be pretty fast. &lt;br&gt;
However, you still have to click on 🐜 button, then ▶ each time you want to run a test. Which I found to be quite a hassle.&lt;/p&gt;

&lt;p&gt;To solve this, in the spirit of my previous article&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/oguimbal" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uuQit23f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--mxiD7-b2--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/236418/38691aba-6383-4916-a062-03729757d054.jpg" alt="oguimbal"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/oguimbal/how-to-never-touch-your-mouse-again-2ppk" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to never touch your mouse again 🐭&lt;/h2&gt;
      &lt;h3&gt;Olivier Guimbal ・ Aug 18 '20 ・ 3 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#vscode&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;I recommend using the commands &lt;code&gt;test-explorer.rerun&lt;/code&gt;, &lt;code&gt;test-explorer.reload&lt;/code&gt;, &lt;code&gt;test-explorer.redebug&lt;/code&gt; and &lt;code&gt;test-explorer.run-this-test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is my key bindings for those:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ctrl+f5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test-explorer.rerun"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ctrl+shift+f5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test-explorer.reload"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ctrl+alt+f5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test-explorer.redebug"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"alt+shift+f5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test-explorer.run-this-test"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>node</category>
      <category>vscode</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How to never touch your mouse again 🐭</title>
      <dc:creator>Olivier Guimbal</dc:creator>
      <pubDate>Tue, 18 Aug 2020 08:12:42 +0000</pubDate>
      <link>https://dev.to/oguimbal/how-to-never-touch-your-mouse-again-2ppk</link>
      <guid>https://dev.to/oguimbal/how-to-never-touch-your-mouse-again-2ppk</guid>
      <description>&lt;h1&gt;
  
  
  VIM ? Well... no thanks.
&lt;/h1&gt;

&lt;p&gt;You may already have met one of those extremists which have explained to you how productive VIM is compared to newbie editors like vscode or other modern useless shit.&lt;/p&gt;

&lt;p&gt;To me, this always have sounded like some sort of hell-yea-i-am-a-real-geek nonsense. In perticular, they often hightlight the fact that VIM is highlly customizable. Weeeelll, yes. That's right. Or at least that &lt;em&gt;was&lt;/em&gt; right: vscode (or other modern alternatives), is also highly customizable, in a way more user friendly fashion.&lt;/p&gt;

&lt;p&gt;However, if like me you have been writing code for decade(s), you might have noticed (or not?) that one of the things that break your flow is to constantly switch between keyboard, arrow keys, and/or your mouse. When you have a burst, you may feel like hell-yea-my-hands-are-flying, but in the end, you spend a lot of time not typing actual code. That is one of the arguments of VIM-extremists, and I must say, this is the one that seduced me the most.&lt;/p&gt;

&lt;h1&gt;
  
  
  What if I dont wanna spend 32752 hours learning/configuring VIM ?
&lt;/h1&gt;

&lt;p&gt;I'll share with you the two ways I achieved that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring vscode alone
&lt;/h2&gt;

&lt;p&gt;Vscode shortcuts customization is awesome. You can do almost anything with it.&lt;/p&gt;

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

&lt;p&gt;Here is &lt;a href="https://gist.github.com/oguimbal/f57106c9597ee65e16dda4e36627aa76" rel="noopener noreferrer"&gt;a link&lt;/a&gt; to my key bindings, so you can pick what's best for you (⚠ my keyboard is AZERTY).&lt;/p&gt;

&lt;p&gt;A config like this one allows you to navigate your code without moving your hands even slightly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;code&gt;ALT+I/J/K/L/U/O/Y/H/M/ù&lt;/code&gt; to move around&lt;/li&gt;
&lt;li&gt;same shortcuts with &lt;code&gt;SHIFT&lt;/code&gt; pressed to select code&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;ALT+Q/S/D/Z&lt;/code&gt; to switch between panes&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;ALT+SHIFT+Q/S/D/Z&lt;/code&gt; to move code panes around&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;ALT+,/;&lt;/code&gt; to switch between tabs&lt;/li&gt;
&lt;li&gt;... it also contains some other useful stuff check it out.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It takes several hours to get used to not touching your mouse, but there is no going back: It really worthes it.&lt;/p&gt;

&lt;p&gt;However, when you configure this kind of shortcuts, it can feel a bit frustrating to edit text elsewhere "the old way" (notepad, word, or even in your browser).&lt;/p&gt;

&lt;p&gt;That is the why of this next section:&lt;/p&gt;

&lt;h2&gt;
  
  
  System-wide configuration using AuthoHotKey (Windows only, sorry)
&lt;/h2&gt;

&lt;p&gt;If you dont know &lt;a href="https://www.autohotkey.com/" rel="noopener noreferrer"&gt;autohotkey&lt;/a&gt;, it is a small software that allows you to write scripts that you can bind to keyboard shortcuts. It has a quite ugly syntax, but it makes it really easy to remap keys and interact with windows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/oguimbal/6953f38c01a94b5e33eb36499950dbd2" rel="noopener noreferrer"&gt;This autohotkey script&lt;/a&gt; will allow you to have almost the same experience moving around text as briefly described in the previous section, but system-wide.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(nb: It also contains a remapping of the F1 key that hides/shows Windows Terminal)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Other utilities
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Jumpy
&lt;/h3&gt;

&lt;p&gt;Moving around code using keyboard is nice, but you may feel like it is frustrating not to jump directly at a precise location visible on your screen (you'll want to &lt;em&gt;click&lt;/em&gt; on this location).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk0aoseuilkcnyf5lcwwn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk0aoseuilkcnyf5lcwwn.gif" alt="jumpy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this, I highly recomend the &lt;a href="https://marketplace.visualstudio.com/items?itemName=wmaurer.vscode-jumpy" rel="noopener noreferrer"&gt;jumpy&lt;/a&gt; vscode extension, which does just that using your keybard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Switcheroo (Windows only)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ALT+Tab&lt;/code&gt; is quite frustrating... try &lt;a href="https://github.com/kvakulo/Switcheroo" rel="noopener noreferrer"&gt;switcheroo&lt;/a&gt;: Press &lt;code&gt;ALT+Enter&lt;/code&gt;, then just type the window name you want to jump to 🎉&lt;/p&gt;

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

&lt;h3&gt;
  
  
  For those who want VIM bindings:
&lt;/h3&gt;

&lt;p&gt;There are several extensions that will turn your vscode experience in something like VIM. Read &lt;a href="https://dev.to/karlredman/navigate-your-vscode-like-its-1999-the-vim-way-3632"&gt;this article&lt;/a&gt; to know more about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  [edit] Vimium
&lt;/h3&gt;

&lt;p&gt;If you want to control your browser mouseless, give a try to &lt;a href="https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb?hl=en" rel="noopener noreferrer"&gt;Vimium&lt;/a&gt; (or &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/vimium-ff/" rel="noopener noreferrer"&gt;here&lt;/a&gt; for Firefox).&lt;/p&gt;

&lt;p&gt;It has plenty of shortcuts allowing you to browse pages, navigate bookmarks, open tabs or click links using your keyboard&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjascks6fn4atkgmj768y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjascks6fn4atkgmj768y.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>vscode</category>
    </item>
    <item>
      <title>i18n - Express/Apollo GraphQL server translation made simple</title>
      <dc:creator>Olivier Guimbal</dc:creator>
      <pubDate>Tue, 04 Aug 2020 16:02:05 +0000</pubDate>
      <link>https://dev.to/oguimbal/i18n-express-apollo-graphql-server-translation-made-simple-33f5</link>
      <guid>https://dev.to/oguimbal/i18n-express-apollo-graphql-server-translation-made-simple-33f5</guid>
      <description>&lt;h1&gt;
  
  
  Table of contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;The problem&lt;/li&gt;
&lt;li&gt;The smarloc approach&lt;/li&gt;
&lt;li&gt;Express.js: How to setup ?&lt;/li&gt;
&lt;li&gt;Apollo GraphQL: How to setup ?&lt;/li&gt;
&lt;li&gt;Generating translations&lt;/li&gt;
&lt;li&gt;Wrapping up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Say you have a server.&lt;br&gt;
Say you are using Express.js and/or Apollo Graphql server.&lt;br&gt;
Say your users speak different languages.&lt;br&gt;
Say you live in 2020, your server is only an api server, and dont care about templating engines.&lt;/p&gt;

&lt;p&gt;🎉 Yey ! This article is for you.&lt;/p&gt;

&lt;p&gt;It introduces &lt;a href="https://github.com/oguimbal/smartloc"&gt;yet another i18n lib&lt;/a&gt; I developped for my company needs which (IMO) simplifies the creation of multi-languages servers implementation.&lt;/p&gt;
&lt;h1&gt;
  
  
  The problem &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;When writing code in an Express route handler, you have access to the original "request" object.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"good"&lt;/em&gt; you would say. &lt;em&gt;I can access "Cookies", "Accept-Languages" header, or whatever that defines my user language, and translate the returned content based on that.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To which I would reply: Okay sure, but do you really want to carry around your request object as an argument of some kind in your whole codebase, just for the sake of knowing your user language ?&lt;/p&gt;

&lt;p&gt;Doesnt it feel kinda wrong ?&lt;/p&gt;

&lt;p&gt;Arent you tired of calling weird static methods with weird syntaxes to get a translated string from your code ?&lt;/p&gt;

&lt;p&gt;Are you really gonna refactor those 500k uni-language code files that you already wrote just to add language support ?&lt;/p&gt;

&lt;p&gt;How the heck are you supposed to store translatable strings ?&lt;/p&gt;

&lt;p&gt;If like me, you feel this is wrong, read on...&lt;/p&gt;
&lt;h1&gt;
  
  
  The smarloc approach. &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;A good example is worth a thousand words:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`Hello, it is now &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// after&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="s2"&gt;`Hello, it is now &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the difference ? Yea, there is 'loc' in front of my string.&lt;br&gt;
Your function is not returning a 'string' anymore, rather a 'LocStr' object.&lt;/p&gt;

&lt;p&gt;Here lies the hack... you dont have to know your user language when you emit the string that will eventually have to be translated. You can pass around this object in your whole app without telling the code that manipulates it that this not an actual string.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wCKWF-_C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sqat1oczu6ge3wxepoc7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wCKWF-_C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sqat1oczu6ge3wxepoc7.gif" alt="latest" width="449" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Translation will then occur at the latest instant, when serializing the json response sent to your client. That's when 'Accept-Language' header or whatever will be read, and when instances of 'LocStr' strings in the returned json will really be translated. At the latest moment.&lt;/p&gt;
&lt;h1&gt;
  
  
  Express.js: How to setup ? &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jwSPHjnY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/i3cu6x6c9ol5tzluv90k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jwSPHjnY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/i3cu6x6c9ol5tzluv90k.png" alt="expressjs" width="435" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First and foremost (this must be done before any code uses smartloc), you'll have to tell which in which language you write you strings in.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="c1"&gt;// lets say our developpers use english in code&lt;/span&gt;
&lt;span class="nx"&gt;setDefaultLocale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you'll add an Express.js middleware which will translate returned json on-the-fly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;translator&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;smartloc/express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;translator&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, it will look for translations matching the 'Accept-Language' header of incoming requests, and will default to the default language you provided.&lt;/p&gt;

&lt;p&gt;You can now use smartloc like this&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// sends a JSON object containing text to translate,&lt;/span&gt;
    &lt;span class="c1"&gt;// without bothering to translate it.&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="c1"&gt;// this string will get an automatic ID&lt;/span&gt;
        &lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="s2"&gt;`Hello !`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="c1"&gt;// notice that you can provide an ID like that&lt;/span&gt;
        &lt;span class="c1"&gt;// and use regular templating syntax:&lt;/span&gt;
        &lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myTime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;`It is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;, mate !`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If  you run this, you'll notice that your api will return things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello !"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"It is &amp;lt;put your date here&amp;gt;, mate !"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Okay, that's fine, but how that doesnt tell us how to provide actual translations to strings...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yes, for that, you'll have to jump to the Generate translations section 🙂&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A simple version of this example is &lt;a href="https://github.com/oguimbal/smartloc/blob/master/samples/graphql/main.ts"&gt;here&lt;/a&gt; (nb: it provides hard-coded translations, not using translation files)&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Apollo GraphQL: How to setup ? &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RAITO8Zk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/je29ur16rff5pks6ffcq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RAITO8Zk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/je29ur16rff5pks6ffcq.png" alt="graphql" width="610" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setting up for an Apollo GraphQL server is almost the same thing as setting up for an Express.js server.&lt;/p&gt;

&lt;p&gt;In short, it is the same as described in the previous section, except you will not have to use the express &lt;code&gt;translator&lt;/code&gt; middleware.&lt;/p&gt;

&lt;p&gt;Instead, you will have to declare in your schema which strings are translatable by using the 'GLocString' type instead of 'GraphQLString', like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;GLocString&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;smartloc/graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;GLocString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="s2"&gt;`Hello !`&lt;/span&gt; &lt;span class="c1"&gt;// will be translated&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then build your apollo server like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;localizeSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;localizedContext&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;smartloc/graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apollo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ApolloServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;localizeSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;localizedContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// build your own context here as usual&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When doing that, all GLocString properties or JSOn properties of your schema will be automatically translated when their resolvers return things containing LocStr instances.&lt;/p&gt;

&lt;p&gt;Then, as with the Express.js explanation, jump to Generate translations section to know how to refresh your translations 🙂&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A simple version of this example is &lt;a href="https://github.com/oguimbal/smartloc/blob/master/samples/graphql/main.ts"&gt;here&lt;/a&gt; (nb: it provides hard-coded translations, not using translation files)&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Generating translations &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;If you're here, I'll assume that you have read one of the previous two sections.&lt;/p&gt;

&lt;p&gt;Lets say you now want to add support for French. First, add something like this in the "scripts" section of your package.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"collect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"smartloc collect --format=json --locales=fr-FR --defaultLocale=en-US --generateDefault"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run &lt;code&gt;npm run collect&lt;/code&gt;, it will (re)generate two files in the i18n directory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;en-us.json&lt;/strong&gt; : You can forget this file, it is here for reference because you put the &lt;code&gt;--generateDefault&lt;/code&gt; option in commandline, and you can provide translations in it (in which case the actual string in code will never reach your client), but you can leave it as it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;fr-fr.json&lt;/strong&gt; : This is where you'll have to put your translations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In these files, translations are grouped by the left dot of strings IDs.&lt;br&gt;
For instance, if you had:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="s2"&gt;`Automatic ID`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;someId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;`Some ID string`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;someGroup.someId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;`Some grouped ID string`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will generate something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"$default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"&amp;lt;sha of your string&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Automatic ID"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"someId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Some ID string"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"someGroup"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"someId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Some grouped ID string"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just add a corresponding "target" to each "source", and you'll be good to go. For instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Some grouped ID string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Une chaine avec ID groupé"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, at startup, just tell smartloc where it should look for translations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;loadAllLocales&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;smartloc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// load all locales in the i18n directory&lt;/span&gt;
&lt;span class="c1"&gt;// ... you could also use loadLocale() to only load one locale file.&lt;/span&gt;
&lt;span class="nx"&gt;loadAllLocales&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;i18n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎉 Here it is ! If your translation files are OK, you'll have a fully functioning multi-language API server !&lt;/p&gt;

&lt;p&gt;I will let you guess how to add more than one translation :)&lt;/p&gt;

&lt;h1&gt;
  
  
  Wrapping up &lt;a&gt;&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;This introduction scratched the surface of what can be done with this lib.&lt;/p&gt;

&lt;p&gt;We've been using it for months @ &lt;a href="https://justice.cool/"&gt;justice.cool&lt;/a&gt; and I must say I am pretty happy with it.&lt;/p&gt;

&lt;p&gt;Before anyone comments something like "you know, there are other libs that" ... I know that there already are plenty of other i18n libs, but I felt like developping a simpler one, which felt good to &lt;strong&gt;me&lt;/strong&gt;. If it doesnt to you, well... that's bad luck mate. Keep using those monsters out there.&lt;/p&gt;

&lt;p&gt;To know a bit more about advanced usages (transform strings, storing translatable strings, manual translations, ... refer to &lt;a href="https://github.com/oguimbal/smartloc"&gt;smartloc repo&lt;/a&gt; ), or open an issue, I'll be glad to answer it.&lt;/p&gt;

</description>
      <category>node</category>
      <category>graphql</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How to really unit test code that uses a DB.</title>
      <dc:creator>Olivier Guimbal</dc:creator>
      <pubDate>Fri, 31 Jul 2020 16:04:01 +0000</pubDate>
      <link>https://dev.to/oguimbal/how-to-really-unit-test-code-that-uses-a-db-3gmg</link>
      <guid>https://dev.to/oguimbal/how-to-really-unit-test-code-that-uses-a-db-3gmg</guid>
      <description>&lt;h1&gt;
  
  
  TLDR
&lt;/h1&gt;

&lt;p&gt;I recently wrote &lt;a href="https://github.com/oguimbal/pg-mem"&gt;a small js lib&lt;/a&gt; that allows you to emulate an  in-memory version of Postgres.&lt;/p&gt;

&lt;p&gt;It is pure js (it works both in browser or with nodejs), and compatible with most query frameworks/ORMs.&lt;/p&gt;

&lt;p&gt;You can play with it on &lt;a href="https://oguimbal.github.io/pg-mem-playground/"&gt;pg-mem playground&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  The problem with unit testing and databases:
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;pg-mem&lt;/code&gt; is compatible with several major ways to connect to a db, but lets assume you are using &lt;a href="https://github.com/vitaly-t/pg-promise"&gt;pg-promise&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When using a DB, you could have methods like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;many&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;select id, name from users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;insert into users(name) values ($1)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you want to unit test things that uses those methods, you would have three options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reimplement a mock "user-service" which replicates what the db essentially does&lt;/li&gt;
&lt;li&gt;hook your request executor (pg-promise, in this case) and tell it "ok, i expect this request to return that".&lt;/li&gt;
&lt;li&gt;create a new clean database on each test run (!!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Either way, this is &lt;strong&gt;not&lt;/strong&gt; reliable nor sustainable as it can lock down implementation details in your unit tests, your mocks can be bugged, or the complexity of testing could explode as your project grows.&lt;/p&gt;
&lt;h1&gt;
  
  
  The solution I came up with
&lt;/h1&gt;

&lt;p&gt;In short, I reimplemented a pure js in-memory version of Postgres.&lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://oguimbal.github.io/pg-mem-playground/"&gt;play with it here&lt;/a&gt; - notice that there are no outgoing queries as you type SQL, but you'll still get the results... yea... sql db, in memory, even in browsers.&lt;/p&gt;

&lt;p&gt;It involved developping two quite heavy parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;a href="https://github.com/oguimbal/pgsql-ast-parser/"&gt;postgresql syntax parser&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;A replication of the PG database engine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But in the end, it works quite well:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newDb&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pg-mem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newDb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;many&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`create table test(id text primary key, value jsonb);
         insert into test values ('key', '{"data": "hello"}');
         select value-&amp;gt;&amp;gt;'data' || ' world' from test;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// guess what this prints ? :)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The only thing you will have to do to unit test your code that issues actual SQL queries: Replace your usual request framework with an instance of it which is bound to a &lt;code&gt;pg-mem&lt;/code&gt; instance instead of an actual database !&lt;/p&gt;

&lt;p&gt;No more thinking about how-the-hell-am-i-going-to-unit-test-that.&lt;/p&gt;

&lt;p&gt;See github repo for examples.&lt;/p&gt;
&lt;h1&gt;
  
  
  Benefits
&lt;/h1&gt;
&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;If you used to run your unit tests against a DB, know that pg-mem is really performant, and implements b-tree indexing.&lt;/p&gt;

&lt;p&gt;Coupled with &lt;a href="https://github.com/oguimbal/vscode-mocha-hmr-sample"&gt;vscode+mocha+hmr&lt;/a&gt;, pg-mem is the perfect match to reach this nice ultra fast development loop, without compromising on your testing quality.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(nb: this is a shameless plug - i'm the forker who implemented hmr support for vscode mocha explorer)&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;This is how running thousands of sql requests feels like with pg-mem and vscode+mocha+hmr :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mfSTwODs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m0mdp8bkon6f78879jap.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mfSTwODs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m0mdp8bkon6f78879jap.gif" alt="run tests" width="880" height="1093"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Actual SQL requests unit-testing
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;pg-mem&lt;/code&gt; parser is not perfect and can fail if you use fancy features, but it is good enough to handle most common features, and it can help you to unit test your requests syntax (if you write sql directly), and test your codes' actual behaviour against a database without having to rely on an actual database (which brings hell in your codebase: stateful unit tests).&lt;/p&gt;
&lt;h3&gt;
  
  
  Index usage unit testing.
&lt;/h3&gt;

&lt;p&gt;(experimental) &lt;code&gt;pg-mem&lt;/code&gt; has its own implementation of indexes. It is far form being perfect, and does not match the way-more-clever behaviour of an actual posgres instance, but it can tell you when there are things that are obiously wrong... you can create a unit test to check that a specific request uses an existing index, for instance. If pg-mem uses an index, I think PG will be clever enough to use it also :)&lt;/p&gt;
&lt;h3&gt;
  
  
  Database immutablility
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;pg-mem&lt;/code&gt; uses immutable data structures under the hood.&lt;br&gt;
This means that you can restore a your database at any previous point in time, with no performance overhead. Quite useful (see ORM section below for an example).&lt;/p&gt;
&lt;h1&gt;
  
  
  If you use an ORM
&lt;/h1&gt;

&lt;p&gt;Most ORMs support creating the schema based on what you described of it =&amp;gt; If you use such an ORM, I recommend this pattern (described here using Typeorm):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// test-db.(js|ts)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newDb&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pg-mem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newDb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;backup&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;orm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createOrm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// close old instance&lt;/span&gt;
    &lt;span class="c1"&gt;// (typeorm has static stuff which prevents intiating multiple connection)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;orm&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;// create new instance&lt;/span&gt;
    &lt;span class="nx"&gt;orm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;adapters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createTypeormConnection&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postgres&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;allYouEntitiesHere&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;backup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// this is the first test to run using this schema&lt;/span&gt;
        &lt;span class="c1"&gt;// ... lets create your tables&lt;/span&gt;
        &lt;span class="c1"&gt;//   (if you have thousands, this could be heavy)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;orm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;synchronize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// custom requests ? fill some shared data, etc...&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;orm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;some sql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Then, create a backup of this empty database with created schema&lt;/span&gt;
        &lt;span class="c1"&gt;// nb: this is instantaneous (o(1))&lt;/span&gt;
        &lt;span class="nx"&gt;backup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Okay, a previous test already create the DB schema&lt;/span&gt;
        &lt;span class="c1"&gt;// =&amp;gt; lets restore data as it was after schema creation&lt;/span&gt;
        &lt;span class="c1"&gt;// nb: this is instantaneous (o(1))&lt;/span&gt;
        &lt;span class="nx"&gt;backup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;restore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;orm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then use this &lt;code&gt;createOrm()&lt;/code&gt; function  in all your unit tests  instead of creating an instance of your ORM the traditional way.&lt;/p&gt;

&lt;p&gt;This way, you will have a clean database on each test run, for free ! (it really is performant in practice...)&lt;/p&gt;
&lt;h1&gt;
  
  
  Work in progress: The future
&lt;/h1&gt;

&lt;p&gt;I intend to develop serveral features in the future, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatic table creation (i.e. if a table does not exist, the db will guess the table to create when you perform insert requests).&lt;/li&gt;
&lt;li&gt;Advanced features of postgres (gin indices, actual introspection, stored procedures, ...)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It currently supports mocking &lt;code&gt;pg&lt;/code&gt;, &lt;code&gt;pg-native&lt;/code&gt; &lt;code&gt;pg-promise&lt;/code&gt; and &lt;code&gt;typeorm&lt;/code&gt; (the latests are  using the two firsts, so their "mock" only are hooks to replace real &lt;code&gt;pg&lt;/code&gt; connection with fake &lt;code&gt;pg&lt;/code&gt; instance in their internal mechanisms)&lt;/p&gt;

&lt;p&gt;See repo for sample usages. Do not hesitate to post issues or comments, and happy unit testing :)&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/oguimbal"&gt;
        oguimbal
      &lt;/a&gt; / &lt;a href="https://github.com/oguimbal/pg-mem"&gt;
        pg-mem
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An in memory postgres DB instance for your unit tests
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
  &lt;a href="https://npmjs.org/package/pg-mem" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/2f764efc069dd5326b6666e99e14c32df9981b5c57f79302c4b56351e3dd2af0/687474703a2f2f696d672e736869656c64732e696f2f6e706d2f762f70672d6d656d2e737667"&gt;&lt;/a&gt;
  &lt;a href="https://npmjs.org/package/pg-mem" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/eb218e20a2ad3b82c7175e01f08513c7f7d8fdb42ad305d61b5cda6b09b84a7e/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f70672d6d656d2e737667"&gt;&lt;/a&gt;
  &lt;a href="https://david-dm.org/oguimbal/pg-mem" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/006587860f0a783327f1158a14d976d0bc43078878df07446e5665fadcbf2e60/68747470733a2f2f64617669642d646d2e6f72672f6f6775696d62616c2f70672d6d656d2e737667"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/oguimbal/pg-mem/workflows/CI/badge.svg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NUt5AuQm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/oguimbal/pg-mem/workflows/CI/badge.svg"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/oguimbal/pg-mem./.github/pg_mem.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T2zz8EpC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/oguimbal/pg-mem./.github/pg_mem.png" width="200"&gt;&lt;/a&gt;
&lt;/p&gt;
 &lt;h3&gt;
pg-mem is an experimental in-memory emulation of a postgres database.&lt;/h3&gt;
&lt;p&gt;
❤ It works both in Node or in the browser
&lt;/p&gt;
&lt;p&gt;
⭐ this repo if you like this package, it helps to motivate me :)
&lt;/p&gt;
&lt;p&gt;
  👉 See it in action with &lt;a href="https://oguimbal.github.io/pg-mem-playground/" rel="nofollow"&gt;pg-mem playground&lt;/a&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/oguimbal/pg-mem#-usage"&gt;Usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oguimbal/pg-mem#-features"&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oguimbal/pg-mem#-libraries-adapters"&gt;Libraries adapters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oguimbal/pg-mem#-inspection"&gt;Inspection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oguimbal/pg-mem#-development"&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/oguimbal/pg-mem/wiki/FAQ"&gt;FAQ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
📐 Usage&lt;/h1&gt;
&lt;h2&gt;
Using Node.js&lt;/h2&gt;
&lt;p&gt;As always, it starts with an:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm i pg-mem --save&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Then, assuming you're using something like webpack, if you're targeting a browser:&lt;/p&gt;
&lt;div class="highlight highlight-source-ts notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;newDb&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"pg-mem"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;db&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;newDb&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-s1"&gt;db&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;public&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;many&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-c"&gt;/* put some sql here */&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
Using Deno&lt;/h2&gt;
&lt;p&gt;Pretty straightforward :)&lt;/p&gt;
&lt;div class="highlight highlight-source-ts notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;newDb&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"https://deno.land/x/pg_mem/mod.ts"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-s1"&gt;db&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;newDb&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-s1"&gt;db&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;public&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;many&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-c"&gt;/* put some sql here */&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
Only use the SQL syntax parser&lt;/h2&gt;
&lt;p&gt;❤ Head to the &lt;a href="https://github.com/oguimbal/pgsql-ast-parser"&gt;pgsql-ast-parser&lt;/a&gt; repo&lt;/p&gt;
&lt;h2&gt;
⚠ Disclaimer&lt;/h2&gt;
&lt;p&gt;…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/oguimbal/pg-mem"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>postgres</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
