<?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: Diego Pasquali</title>
    <description>The latest articles on DEV Community by Diego Pasquali (@dgopsq).</description>
    <link>https://dev.to/dgopsq</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%2F748560%2F6f2d721b-b412-43fc-9a75-ec4913e63428.jpeg</url>
      <title>DEV Community: Diego Pasquali</title>
      <link>https://dev.to/dgopsq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dgopsq"/>
    <language>en</language>
    <item>
      <title>A ripgrep-powered Search Engine on the web</title>
      <dc:creator>Diego Pasquali</dc:creator>
      <pubDate>Fri, 09 Sep 2022 09:49:23 +0000</pubDate>
      <link>https://dev.to/dgopsq/a-ripgrep-powered-search-engine-on-the-web-1aml</link>
      <guid>https://dev.to/dgopsq/a-ripgrep-powered-search-engine-on-the-web-1aml</guid>
      <description>&lt;p&gt;My &lt;a href="https://diegopasquali.com/search" rel="noopener noreferrer"&gt;website’s search&lt;/a&gt; is using &lt;a href="https://github.com/BurntSushi/ripgrep" rel="noopener noreferrer"&gt;&lt;strong&gt;ripgrep&lt;/strong&gt;&lt;/a&gt; under the hood. You can try it out visiting the &lt;a href="https://www.diegopasquali.com/search" rel="noopener noreferrer"&gt;search page&lt;/a&gt; and typing a &lt;a href="https://docs.rs/regex/1.6.0/regex/#syntax" rel="noopener noreferrer"&gt;simple regex&lt;/a&gt;. As a disclaimer I just want to say that this is mostly an experiment and it’s in no way a real alternative to do Full-Text Search… but IT IS cool 😎✨&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The result of this article is &lt;a href="https://github.com/dgopsq/netgrep" rel="noopener noreferrer"&gt;&lt;em&gt;netgrep&lt;/em&gt;&lt;/a&gt;, a JavaScript module that provides an API to execute HTTP based search queries using most of the &lt;em&gt;ripgrep&lt;/em&gt;’s features. You can take a look at the code right away since it should be decently commented 🤓&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  The idea
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/BurntSushi/ripgrep" rel="noopener noreferrer"&gt;&lt;em&gt;ripgrep&lt;/em&gt;&lt;/a&gt; is an interesting software that allows to do regex-based search queries to files and directories recursively. The most important part is that &lt;strong&gt;it’s fast&lt;/strong&gt; like, really fast. So, could it be possible to make it works over HTTP instead of the filesystem? And what about using it in the browser?&lt;/p&gt;

&lt;p&gt;Turned out that it actually IS possible to use it over HTTP since there is a &lt;a href="https://github.com/BurntSushi/ripgrep/tree/master/crates/grep" rel="noopener noreferrer"&gt;Rust create&lt;/a&gt; with all the essential code to make &lt;em&gt;ripgrep&lt;/em&gt; works programmatically. About the “work in the browser” thing the story is a bit more complicated. Since we are talking about a Rust library, the most common way to use it is through WebAssembly (WASM). The &lt;em&gt;ripgrep&lt;/em&gt;’s codebase is mostly compatible with some exception which I had to manually fix &lt;a href="https://github.com/dgopsq/ripgrep" rel="noopener noreferrer"&gt;inside a fork&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, now that we have everything sorted out, let's go a bit deeper!&lt;/p&gt;

&lt;h1&gt;
  
  
  The implementation
&lt;/h1&gt;

&lt;p&gt;The &lt;a href="https://github.com/dgopsq/netgrep" rel="noopener noreferrer"&gt;netgrep&lt;/a&gt; library is divided into two macro parts: a &lt;strong&gt;WASM binary&lt;/strong&gt; that interacts with the &lt;em&gt;ripgrep&lt;/em&gt;’s internals and a &lt;strong&gt;TypeScript library&lt;/strong&gt; which manages the bindings and the exposed API. I also wanted to try &lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;nx&lt;/a&gt; as a build system, which is quite good for a Rust + TS codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  WASM binary
&lt;/h2&gt;

&lt;p&gt;After dealing with the WASM compatibility issue, which was actually &lt;a href="https://github.com/BurntSushi/ripgrep/commit/645cb7e3baf7c2b286d652c3c960fcd45978c0fd" rel="noopener noreferrer"&gt;quite simple to fix&lt;/a&gt;, I had to choose the &lt;em&gt;architecture&lt;/em&gt; of the library. Analysing a bit &lt;em&gt;ripgrep&lt;/em&gt; we can summarise its work into two sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Discovery&lt;/strong&gt; which is the act of navigating inside a directory and list all the files recursively;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search&lt;/strong&gt; or: “look for the given pattern inside that file”.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the moment I just wanted to release &lt;em&gt;netgrep&lt;/em&gt; with only the &lt;strong&gt;Search&lt;/strong&gt; feature, leaving to the user the job of providing a list of files to analyse. Taking this into consideration and knowing that a WASM binary can only use the native browser APIs for networking (so &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API" rel="noopener noreferrer"&gt;fetch&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest" rel="noopener noreferrer"&gt;XMLHttpRequest&lt;/a&gt;), I decided to handle just the &lt;strong&gt;searching&lt;/strong&gt; function inside the binary.&lt;/p&gt;

&lt;p&gt;More specifically, the &lt;a href="https://github.com/dgopsq/netgrep/blob/main/packages/search/src/lib.rs#L12" rel="noopener noreferrer"&gt;&lt;code&gt;search_bytes&lt;/code&gt;&lt;/a&gt; function exposed from the &lt;a href="https://github.com/dgopsq/netgrep/blob/main/packages/search" rel="noopener noreferrer"&gt;&lt;strong&gt;search&lt;/strong&gt; package&lt;/a&gt; uses the &lt;code&gt;search_slice&lt;/code&gt; method from the &lt;code&gt;grep&lt;/code&gt; crate to analyse a slice of bytes, returning a boolean value representing whether the given pattern has been found or not. This allows for a great deal of flexibility, for example we’ll be able to check for a pattern &lt;em&gt;while a file is being downloaded&lt;/em&gt; and not just after, leveraging one of the most useful features of &lt;em&gt;ripgrep&lt;/em&gt; even over HTTP.&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript library
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/dgopsq/netgrep/tree/main/packages/netgrep" rel="noopener noreferrer"&gt;&lt;strong&gt;netgrep&lt;/strong&gt; package&lt;/a&gt; is the one responsible to expose the final API to the user, and the “core” function used to build all the other methods is &lt;a href="https://github.com/dgopsq/netgrep/blob/main/packages/netgrep/src/lib/Netgrep.ts#L50" rel="noopener noreferrer"&gt;&lt;code&gt;Netgrep.search()&lt;/code&gt;&lt;/a&gt;. This just executes a &lt;code&gt;fetch&lt;/code&gt; request toward an endpoint and triggers the &lt;code&gt;search_bytes&lt;/code&gt; function for every batch of bytes downloaded until a match has been found. When this happens it will just resolve the returned &lt;code&gt;Promise&lt;/code&gt; with a &lt;a href="https://github.com/dgopsq/netgrep/blob/main/packages/netgrep/src/lib/data/NetgrepResult.ts" rel="noopener noreferrer"&gt;&lt;code&gt;NetgrepResult&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The curious part here is how to read-while-downloading using JavaScript. At first I just tried using an &lt;code&gt;XMLHttpRequest&lt;/code&gt; with an &lt;code&gt;onprogress&lt;/code&gt; event, but I noticed that I couldn’t actually read the &lt;em&gt;content&lt;/em&gt; being downloaded. Trying reading the response’s value was a dead end-ish too, since as stated in the official documentation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[…] The value is null if the request is not yet complete or was unsuccessful, with the exception that when reading text data using a responseType of "text" or the empty string (""), the response can contain the response so far while the request is still in the LOADING &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState" rel="noopener noreferrer"&gt;readyState&lt;/a&gt; (3).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even though this is an interesting tradeoff, there is a better (this is &lt;em&gt;opinionated&lt;/em&gt; obviously) approach using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams#reading_the_stream" rel="noopener noreferrer"&gt;&lt;code&gt;fetch&lt;/code&gt; + &lt;code&gt;ReadableStream&lt;/code&gt;&lt;/a&gt; allowing us to read a network response “chunk by chunk”. I &lt;del&gt;copied the example&lt;/del&gt; implemented it inside the &lt;code&gt;search&lt;/code&gt; method &lt;a href="https://github.com/dgopsq/netgrep/blob/main/packages/netgrep/src/lib/Netgrep.ts#L95-L102" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All the other methods like &lt;code&gt;searchBatch&lt;/code&gt; and &lt;code&gt;searchBatchWithCallback&lt;/code&gt; are utility functions built over &lt;code&gt;search&lt;/code&gt; that will provide a nice (or at least I hope 🥹) dev experience using this library.&lt;/p&gt;

&lt;h1&gt;
  
  
  What about performance?
&lt;/h1&gt;

&lt;p&gt;Well, as I said this was just an experiment to test a bit WASM and the integration of a library that is completely outside the "web" scope. This means that even though I have written it with performance in mind, &lt;strong&gt;it’s not the best way to do a &lt;a href="https://en.wikipedia.org/wiki/Full-text_search" rel="noopener noreferrer"&gt;Full-Text Search&lt;/a&gt;&lt;/strong&gt;. It could be used for small files-based databases (like this blog) and possibly with a server &lt;a href="https://http2.github.io/faq/#why-is-http2-multiplexed" rel="noopener noreferrer"&gt;supporting HTTP/2 in order to leverage multiplexing&lt;/a&gt;. Anything bigger than that will probably require a more “scalable” approach like an Index-Based Search Engine.&lt;/p&gt;

&lt;p&gt;See ya in the next article 👋&lt;/p&gt;

</description>
      <category>search</category>
      <category>typescript</category>
      <category>rust</category>
      <category>grep</category>
    </item>
    <item>
      <title>Inflist, an experiment using PureScript and React</title>
      <dc:creator>Diego Pasquali</dc:creator>
      <pubDate>Fri, 13 May 2022 10:31:56 +0000</pubDate>
      <link>https://dev.to/dgopsq/inflist-an-experiment-using-purescript-and-react-4odj</link>
      <guid>https://dev.to/dgopsq/inflist-an-experiment-using-purescript-and-react-4odj</guid>
      <description>&lt;p&gt;One of the resolutions for this year was to learn a bit more seriously PureScript (or at least die trying). I started writing small stuff like exercises and little scripts, and all went quite good. I felt like I had a tighter grasp on the language, and with that I felt more confident. It was time to create something bigger that I could actually compare with the code I write daily. So I decided to create a whole (mini) web application, and since it’s a bit of a tradition, why not a Todo List 🤓?&lt;/p&gt;

&lt;p&gt;This Todo List has three main features: it should be infinitely nestable (or it should be possible to create a todo inside another todo without limitations), each todo should be freely editable without any friction and a todo should have optional notes.&lt;/p&gt;

&lt;p&gt;So, I had a clear idea of what to create, and more importantly a name! Time to go a bit deeper ✌️.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are curious, there is a &lt;a href="https://github.com/dgopsq/purescript-inflist" rel="noopener noreferrer"&gt;GitHub repo with a decently commented code&lt;/a&gt; and a &lt;a href="https://www.inflist.xyz/" rel="noopener noreferrer"&gt;live example&lt;/a&gt; you can play with 🕹.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Technologies
&lt;/h1&gt;

&lt;p&gt;First of all I had to choose what to use to manage the User Interface. I narrowed down to two modules: &lt;a href="https://github.com/purescript-halogen/purescript-halogen" rel="noopener noreferrer"&gt;Halogen&lt;/a&gt; and &lt;a href="https://github.com/megamaddu/purescript-react-basic-hooks" rel="noopener noreferrer"&gt;react-basic-hooks&lt;/a&gt; (which is a “wrapper” of the unmaintained &lt;a href="https://github.com/lumihq/purescript-react-basic" rel="noopener noreferrer"&gt;react-basic&lt;/a&gt;). I decided to go with &lt;strong&gt;react-basic-hooks&lt;/strong&gt; just because I work with &lt;strong&gt;React&lt;/strong&gt; on a daily basis and I wanted to understand its interoperability with PureScript. I will 10/10 try &lt;strong&gt;Halogen&lt;/strong&gt; too in the next future since as far as I can see is the most famous and maintained in the PureScript community.&lt;/p&gt;

&lt;p&gt;Another technology I use regularly is &lt;strong&gt;Redux&lt;/strong&gt;. But this time I wanted to manage the global state in a simpler and clearer way just using React hooks. I decided to go with a simple &lt;code&gt;useReducer&lt;/code&gt; combined with the&lt;a href="https://github.com/dai-shi/use-context-selector" rel="noopener noreferrer"&gt;&lt;code&gt;useContextSelector&lt;/code&gt; hook&lt;/a&gt; which will avoid the whole application’s re-render caused by the native &lt;code&gt;useContext&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;And finally, for the styles I opted for the most famous &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Architecture
&lt;/h1&gt;

&lt;p&gt;The whole point of using PureScript is to adopt a pure FP architecture, having all the “side effect” moved at the very edge of the implementation. I really like this approach instead of a “partial” FP one given by non pure-functional languages. For example, when using TypeScript you might have various functional “bubbles” here and there in the code, but multiple “entry point” for side effects. This is not wrong but it’s not really leveraging the full power of functional programming which is: &lt;strong&gt;Types&lt;/strong&gt;! Problems like &lt;em&gt;Dependency Injection&lt;/em&gt; (take a look at &lt;a href="https://mmhaskell.com/monads/reader-writer" rel="noopener noreferrer"&gt;the Reader monad&lt;/a&gt;) or executing operations in the right order (see the &lt;a href="https://qiita.com/kimagure/items/a0ee7313e8c7690bf3f5" rel="noopener noreferrer"&gt;Indexed Monad&lt;/a&gt; generalisation, which is the core of &lt;em&gt;react-basic-hooks&lt;/em&gt;) are magically solved right inside the language.&lt;/p&gt;

&lt;p&gt;Following this path and with the idea that Inflist is just a PoC, I decided to tackle the application’s architecture optimising the performances at the expenses of stability. A “todo” inside Inflist is just a branch in a tree with a unique id, a single parent and multiple children:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cd"&gt;-- | A data structure representing a Todo.&lt;/span&gt;
&lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Todo&lt;/span&gt;
  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;TodoId&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;checked&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Boolean&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;children&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="kt"&gt;TodoId&lt;/span&gt;
    &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;TodoId&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is quite convenient for two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It’s easy to persist. For example using the &lt;strong&gt;Local Storage&lt;/strong&gt; we can store each todo as a single entity with an id and the JSON serialisation of the todo itself as the value. This allows us to have decent performances even using the simplest storage system.&lt;/li&gt;
&lt;li&gt;We can show every todo as a standalone entity. Since &lt;em&gt;everything&lt;/em&gt; is a todo and each todo is linked with its parent, starting the application from the root todo or from a deep one is the same thing. This is really helpful for both development experience and features like the navigation (creating a permalink for a todo is basically automatically implemented).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is obviously not perfect, there are problems which are solved using &lt;em&gt;User Interface&lt;/em&gt; tricks, like the &lt;code&gt;[...]&lt;/code&gt; in the breadcrumb that saves us the hassle of traversing the whole tree.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;navigation&lt;/strong&gt; is handled through &lt;a href="https://github.com/purescript-contrib/purescript-routing" rel="noopener noreferrer"&gt;purescript-routing&lt;/a&gt; which provides an interface for the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/History/pushState" rel="noopener noreferrer"&gt;PushState API&lt;/a&gt; and a convenient way to parse the routes starting from a simple ADT:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="cd"&gt;-- | This is the data structure that describes the&lt;/span&gt;
&lt;span class="cd"&gt;-- | application's routes.&lt;/span&gt;
&lt;span class="kr"&gt;data&lt;/span&gt; &lt;span class="kt"&gt;AppRoute&lt;/span&gt;
  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;RootTodos&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;ChildrenTodos&lt;/span&gt; &lt;span class="kt"&gt;TodoId&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most “unstable” part is probably the logic dealing with the &lt;strong&gt;storage&lt;/strong&gt;. There is a persistence layer inside Inflist passed around as a dependency, and its only implementation is using the &lt;strong&gt;Local Storage&lt;/strong&gt; as anticipated. This layer is executed directly through the React components using native hooks like &lt;a href="https://github.com/megamaddu/purescript-react-basic-hooks/blob/57ecbe7478a0975783bdc0f0639a851329970947/src/React/Basic/Hooks/Aff.purs#L26-L63" rel="noopener noreferrer"&gt;useAff&lt;/a&gt;, and thus managed by the React lifecycle events. This can definitely be improved using a more solid approach from libraries like &lt;a href="https://redux-saga.js.org/" rel="noopener noreferrer"&gt;Redux-Saga&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;As I said, this (really small) project was just an experiment to better understand PureScript and its advantages and disadvantages. These are the lessons I learned:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A pure-FP language, and more in specific PureScript, &lt;strong&gt;is a viable alternative for the most dangerous parts of an application&lt;/strong&gt;. When a specific component or micro frontend needs to be particularly “stable”, using PureScript would definitely save time dealing with common bugs or errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The learning curve for PureScript is *really steep.&lt;/strong&gt;* Without the understanding of common FP concepts it can be really difficult to create even simple things. I’m &lt;em&gt;sure&lt;/em&gt; there are errors in Inflist, specifically in the typization of foreign JavaScript code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The developer experience is good but it's bad.&lt;/strong&gt; In a functional codebase everything must (should) be typed, the enormous quantity of errors catched at compile time is definitely a plus for the overall developer experience. The only downside, and this is something related directly to PureScript, it's that the IDE support is a bit weak. It's possible to get the compilation errors in real-time and there are tooltips to show description of types and functions, but for example something I missed a lot from Scala FP is the inferred types of computed values (for example, assignments inside a &lt;code&gt;do&lt;/code&gt; block).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The community is still quite small&lt;/strong&gt; compared to other languages, and there is a lack of modules and tools. On the other side PureScript's interoperability is &lt;em&gt;✨ awesome ✨&lt;/em&gt; making using third-party libraries from JavaScript a breeze. I would also like to point out that, as far as I can see, &lt;strong&gt;all the mainteiners of the major modules are really present and active&lt;/strong&gt; inside the community, even in the official &lt;a href="https://purescript.org/chat" rel="noopener noreferrer"&gt;Discord server&lt;/a&gt;!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Well, that's all 🙏&lt;/p&gt;

</description>
      <category>purescript</category>
      <category>functional</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using the fp-ts TaskEither monad with Redux-Saga</title>
      <dc:creator>Diego Pasquali</dc:creator>
      <pubDate>Mon, 17 Jan 2022 21:31:19 +0000</pubDate>
      <link>https://dev.to/dgopsq/using-the-fp-ts-taskeither-monad-with-redux-saga-37lp</link>
      <guid>https://dev.to/dgopsq/using-the-fp-ts-taskeither-monad-with-redux-saga-37lp</guid>
      <description>&lt;p&gt;The &lt;a href="https://gcanti.github.io/fp-ts/modules/TaskEither.ts.html" rel="noopener noreferrer"&gt;fp-ts &lt;code&gt;TaskEither&amp;lt;L, R&amp;gt;&lt;/code&gt; monad&lt;/a&gt; is a powerful data structure representing an asynchronous computation returning a value of type &lt;code&gt;R&lt;/code&gt; when successful or a value of type &lt;code&gt;L&lt;/code&gt; on failure. It allows to handle errors in a more "functional" and transparent way instead of dealing with exceptions (😖).&lt;/p&gt;

&lt;p&gt;I recently found myself using it inside &lt;a href="https://redux-saga.js.org/" rel="noopener noreferrer"&gt;Redux-Saga&lt;/a&gt;, executing functions returning a &lt;code&gt;TaskEither&lt;/code&gt; using the &lt;code&gt;call&lt;/code&gt; effect. Now, it's actually quite easy to do so since &lt;code&gt;TaskEither&lt;/code&gt; is just a function returning a &lt;code&gt;Promise&lt;/code&gt;. At first glance we can just do something 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="c1"&gt;// The service returning a `TaskEither`.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;param&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="nx"&gt;TE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;TE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;right&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hello World, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;param&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// The saga executing the service.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;saga&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Either&amp;lt;Error, string&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;service&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;param&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;yield*&lt;/code&gt; operator here is used for &lt;a href="https://github.com/agiledigital/typed-redux-saga" rel="noopener noreferrer"&gt;typed-redux-saga&lt;/a&gt;, to obtain a better typing inside a &lt;em&gt;Saga&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this way, &lt;code&gt;result&lt;/code&gt; would actually be of type &lt;code&gt;Either&amp;lt;Error, string&amp;gt;&lt;/code&gt;, but we are using &lt;code&gt;call&lt;/code&gt; wrongly by calling the function directly instead of passing its arguments like &lt;code&gt;call(service, 'param')&lt;/code&gt;. This will cause problems when writing unit tests for the &lt;em&gt;Saga&lt;/em&gt;. So, what if we pass the service in the correct way? Then we would have to write:&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;// TaskEither&amp;lt;Error, string&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unexecutedResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;param&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Either&amp;lt;Error, string&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unexecutedResult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, &lt;code&gt;unexecutedResult&lt;/code&gt; is of type &lt;code&gt;TaskEither&amp;lt;Error, string&amp;gt;&lt;/code&gt;, and we would still need to actually execute it to obtain the concrete result. This works, but we would have to test two &lt;code&gt;call&lt;/code&gt; effects for a single "operation". Don't really like it 😾. With a bit of TypeScript magic though, we can improve it by writing a utility function that creates and executes the &lt;code&gt;TaskEither&lt;/code&gt; in a single call:&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="cm"&gt;/**
 * Utility to evaluate a function returning a `TaskEither`.
 */&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;callTaskEither&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Fn&lt;/span&gt; &lt;span class="nf"&gt;extends &lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;genericArgs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;TE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Parameters&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Fn&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;SagaGenerator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Evaluate a one-argument function returning a TaskEither.
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;callTaskEither1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;P1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;P1&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;TE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;P1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;SagaGenerator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;callTaskEither&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Helper type for `callTaskEither1`.
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;TCallTaskEither1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;P1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;P1&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;TE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;P1&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;SagaGenerator&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Either&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function &lt;code&gt;callTaskEither&lt;/code&gt; is just a generator that does the two &lt;code&gt;call&lt;/code&gt; we described before. Since TypeScript would be in trouble inferring the function's parameters with the spread operator, we need to create helper functions and types manually for each number of parameters we need. It's not the best but it's a one-time only job! This hard work will allow us to have a working type-check using a single &lt;code&gt;call&lt;/code&gt; effect, 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="c1"&gt;// Either&amp;lt;Error, string&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TCallTaskEither1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Error&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="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;callTaskEither1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;param&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still a little verbose, but I actually prefer it to using two &lt;code&gt;call&lt;/code&gt; effects everywhere!&lt;/p&gt;

&lt;p&gt;See ya 🤠&lt;/p&gt;

</description>
      <category>functional</category>
      <category>redux</category>
      <category>typescript</category>
      <category>saga</category>
    </item>
    <item>
      <title>Reading from the Standard Input (stdin) using PureScript</title>
      <dc:creator>Diego Pasquali</dc:creator>
      <pubDate>Thu, 30 Dec 2021 10:19:19 +0000</pubDate>
      <link>https://dev.to/dgopsq/reading-from-the-standard-input-stdin-using-purescript-2hdh</link>
      <guid>https://dev.to/dgopsq/reading-from-the-standard-input-stdin-using-purescript-2hdh</guid>
      <description>&lt;p&gt;These last few weeks I started learning PureScript again. I &lt;em&gt;love&lt;/em&gt; this language, it’s the quintessence of functional programming, but it lacks in community and libraries compared for example to TypeScript, and this sadly makes it really difficult for me to use in my side projects.&lt;/p&gt;

&lt;p&gt;While I was doing some challenges online, I had the need to retrieve an input string from &lt;code&gt;stdin&lt;/code&gt;. I found out that this case is not really well covered anywhere, so why not writing a new blog post? 🙃&lt;/p&gt;

&lt;p&gt;First of all, to read from the &lt;strong&gt;Standard Input (stdin)&lt;/strong&gt; the library &lt;a href="https://github.com/purescript-node/purescript-node-process" rel="noopener noreferrer"&gt;purescript-node-process&lt;/a&gt; is needed. This library exposes &lt;code&gt;stdin&lt;/code&gt; which is a &lt;code&gt;Readable&lt;/code&gt; (a simple readable stream) and it will be the key component around which we’ll create our function. Since we are dealing with a simple stream, what we want to create is a function that takes that same stream and return a new string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Prelude&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Control.Monad.ST.Class&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;liftST&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Control.Monad.ST.Ref&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;STRef&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Either&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Either&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Effect&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Effect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Effect.Aff&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;effectCanceler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;launchAff_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;makeAff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Effect.Aff.Class&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;MonadAff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;liftAff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Effect.Class&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;liftEffect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Effect.Console&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Node.Encoding&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Node.Process&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;stdin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Node.Stream&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Readable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;onDataString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;onEnd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;-- Accumulate a readable stream inside a string.&lt;/span&gt;
&lt;span class="n"&gt;streamAccumulator&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;forall&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="kt"&gt;MonadAff&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Readable&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
&lt;span class="n"&gt;streamAccumulator&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;liftAff&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;makeAff&lt;/span&gt;
    &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
        &lt;span class="c1"&gt;-- Create a mutable reference using `purescript-st`.&lt;/span&gt;
        &lt;span class="n"&gt;inputRef&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;liftST&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;STRef&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;

        &lt;span class="c1"&gt;-- Handle the `onDataString` event using&lt;/span&gt;
        &lt;span class="c1"&gt;-- the UTF8 encoding.&lt;/span&gt;
        &lt;span class="n"&gt;onDataString&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="kt"&gt;UTF8&lt;/span&gt; &lt;span class="nf"&gt;\&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
          &lt;span class="n"&gt;void&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;liftST&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;STRef&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;modify&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;inputRef&lt;/span&gt;

        &lt;span class="c1"&gt;-- Handle the `onEnd` event.&lt;/span&gt;
        &lt;span class="n"&gt;onEnd&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
          &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;liftST&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;STRef&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="n"&gt;inputRef&lt;/span&gt;
          &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Right&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;

        &lt;span class="c1"&gt;-- Handle the `onError` event.&lt;/span&gt;
        &lt;span class="n"&gt;onError&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="kt"&gt;Left&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;

        &lt;span class="c1"&gt;-- Return a `Canceler` effect that will&lt;/span&gt;
        &lt;span class="c1"&gt;-- destroy the stream.&lt;/span&gt;
        &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;effectCanceler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;destroy&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;-- Execute the program.&lt;/span&gt;
&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Effect&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt;
&lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="n"&gt;launchAff_&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;streamAccumulator&lt;/span&gt; &lt;span class="n"&gt;stdin&lt;/span&gt;
    &lt;span class="n"&gt;liftEffect&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks a bit messy but it’s actually simple. Since the process of handling a stream is “event-driven” we are going to use a safe mutable string (from &lt;a href="https://github.com/purescript/purescript-st" rel="noopener noreferrer"&gt;purescript-st&lt;/a&gt;) to accumulate our input every time the &lt;code&gt;onDataString&lt;/code&gt; event will be triggered. This whole process is asynchronous, meaning that we have to wait for the &lt;code&gt;onEnd&lt;/code&gt; event (or &lt;code&gt;onError&lt;/code&gt; if something bad happened) to actually return the accumulated string. The effect monad &lt;code&gt;Aff&lt;/code&gt; solves this through &lt;code&gt;makeAff&lt;/code&gt;. The &lt;code&gt;res&lt;/code&gt; callback has to be called with an &lt;code&gt;Either&lt;/code&gt; parameter, and only when this callback will be triggered the program can continue its execution.&lt;/p&gt;

&lt;p&gt;Peace ✌️&lt;/p&gt;

</description>
      <category>purescript</category>
      <category>functional</category>
      <category>stdin</category>
      <category>stream</category>
    </item>
    <item>
      <title>Using Auth0 with Expo in the Managed Workflow</title>
      <dc:creator>Diego Pasquali</dc:creator>
      <pubDate>Fri, 09 Jul 2021 08:21:28 +0000</pubDate>
      <link>https://dev.to/dgopsq/using-auth0-with-expo-in-the-managed-workflow-33lj</link>
      <guid>https://dev.to/dgopsq/using-auth0-with-expo-in-the-managed-workflow-33lj</guid>
      <description>&lt;p&gt;Here I am, once again writing something about Expo! Today I want to cover an interesting argument, which is the integration with &lt;a href="https://auth0.com/docs/connections/identity-providers-social" rel="noopener noreferrer"&gt;Auth0&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Auth0
&lt;/h2&gt;

&lt;p&gt;Auth0 is an authentication (and authorization) platform providing a lot of very useful features to allow users to signup and login into your application. Whether you need a full oAuth2 authentication flow, or a simple username/password login with Auth0 you will have it implemented in just a few lines of code.&lt;/p&gt;

&lt;p&gt;Personally I'm quite positive using these technologies while building a new application, especially when you have very sensible data. Managing the users and their credentials is always a delicate subject and most of the time much more expensive than a monthly subscription.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compatibility with Expo
&lt;/h2&gt;

&lt;p&gt;When in our team decided to use Auth0 and Expo the first thing I did was check for the compatibility. Expo is awesome to build applications using React Native, but it's a bit of a walled garden: features like the &lt;em&gt;Cloud Building&lt;/em&gt; and &lt;em&gt;over-the-air updates&lt;/em&gt; are specific for the &lt;strong&gt;Managed Workflow&lt;/strong&gt; and will work out of the box just using supported Expo modules. When we need to &lt;em&gt;eject&lt;/em&gt; an Expo app to use a particular React Native library or because we need to go a bit more "low level" we are talking about the &lt;strong&gt;Bare Workflow&lt;/strong&gt; (&lt;a href="https://docs.expo.io/introduction/managed-vs-bare/" rel="noopener noreferrer"&gt;here&lt;/a&gt; you can find more details about this topic).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With the new &lt;a href="https://docs.expo.io/build/introduction/" rel="noopener noreferrer"&gt;EAS Build&lt;/a&gt; this requirement has been removed. We can build a React Native application in the cloud and have over-the-air updates even in &lt;strong&gt;Bare Workflows&lt;/strong&gt;, although it's still a preview feature.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Turns out that Auth0 is not &lt;em&gt;effectively&lt;/em&gt; supported by Expo. When there's not an &lt;code&gt;expo-something&lt;/code&gt; module and the library to integrate needs a &lt;code&gt;pod install&lt;/code&gt; (&lt;a href="https://auth0.com/docs/quickstart/native/react-native/00-login" rel="noopener noreferrer"&gt;here the link&lt;/a&gt; to the Auth0 React Native SDK) usually we can conclude that we'll have to eject our application from the magical Expo garden.&lt;/p&gt;

&lt;p&gt;Luckily this was not the case! 🥳&lt;/p&gt;

&lt;h2&gt;
  
  
  The integration
&lt;/h2&gt;

&lt;p&gt;Following the tutorial I linked before, and more specifically the &lt;a href="https://github.com/auth0/react-native-auth0#ios" rel="noopener noreferrer"&gt;Github repo&lt;/a&gt; we can see that the Objective-C binding described is just needed to open a browser page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight objective_c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#import &amp;lt;React/RCTLinkingManager.h&amp;gt;
&lt;/span&gt;
&lt;span class="k"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BOOL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;UIApplication&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;app&lt;/span&gt; &lt;span class="nf"&gt;openURL&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;NSURL&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;
            &lt;span class="nf"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;NSDictionary&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UIApplicationOpenURLOptionsKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;options&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RCTLinkingManager&lt;/span&gt; &lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="nf"&gt;openURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;options&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 rest of the stuff in the tutorial are just changes to the &lt;code&gt;Info.plist&lt;/code&gt; file, and they can be done easily without ejecting our application through the &lt;code&gt;app.config.ts&lt;/code&gt; (or &lt;code&gt;app.json&lt;/code&gt;) modifying the &lt;code&gt;ios.infoPlist&lt;/code&gt; value:&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;appConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ExpoConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="na"&gt;ios&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;infoPlist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;CFBundleURLTypes&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="na"&gt;CFBundleTypeRole&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;None&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;CFBundleURLName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;CFBundleURLSchemes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$(PRODUCT_BUNDLE_IDENTIFIER)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="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;We &lt;strong&gt;don't&lt;/strong&gt; really need to add these lines though because using the SDK without linking it with the React Native ecosystem through &lt;code&gt;pod install&lt;/code&gt; will allow us to &lt;strong&gt;only use the functions that do not need to open a browser window or handle deep links&lt;/strong&gt;, like &lt;code&gt;passwordRealm&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;auth0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;passwordRealm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello@email.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;best_password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;realm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UsernamePasswordConnection&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Auth0 web-based authentication
&lt;/h2&gt;

&lt;p&gt;Even if we can't use the SDK for a web-based authentication, we can still leverage the &lt;a href="https://auth0.com/docs/api" rel="noopener noreferrer"&gt;Auth0 API&lt;/a&gt; and the &lt;a href="https://docs.expo.io/versions/latest/sdk/auth-session/" rel="noopener noreferrer"&gt;AuthSession&lt;/a&gt; component from Expo. With AuthSession we can let the user do a complete authentication flow in the browser (such as oAuth). The module will start a browser session and will listen for the user to come back into the application through a &lt;a href="https://docs.expo.io/guides/linking/" rel="noopener noreferrer"&gt;Deep Link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To start using Auth0 with AuthSession we first need to setup a &lt;a href="https://auth0.com/learn/social-login/" rel="noopener noreferrer"&gt;Social Login&lt;/a&gt; on the Auth0 dashboard. After that we need to start an authentication session pointing to &lt;code&gt;https://your-domain.auth0.com/authorize&lt;/code&gt; with the &lt;a href="https://auth0.com/docs/api/authentication#social" rel="noopener noreferrer"&gt;correct query parameters&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;returnUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;AuthSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makeRedirectUri&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;queryParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toQueryString&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;response_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;token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;client_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;client_id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;connection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;redirect_uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;returnUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/authorize?&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;queryParams&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;

&lt;span class="nx"&gt;AuthSession&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startAsync&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;returnUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;authUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code will open a browser page to the Auth0 endpoint, redirecting the user to the specific authentication provider based on the &lt;code&gt;connection&lt;/code&gt; parameter. The &lt;code&gt;returnUrl&lt;/code&gt; variable contains the deep link URL of our application and AuthSession will be waiting for the user to be redirected back there signaling the authentication flow's end.&lt;/p&gt;

&lt;p&gt;That's all! ✌️&lt;/p&gt;

</description>
      <category>expo</category>
      <category>reactnative</category>
      <category>auth0</category>
      <category>authentication</category>
    </item>
    <item>
      <title>Handling migrations in React Native with SQLite and fp-ts</title>
      <dc:creator>Diego Pasquali</dc:creator>
      <pubDate>Tue, 15 Sep 2020 08:17:58 +0000</pubDate>
      <link>https://dev.to/dgopsq/handling-migrations-in-react-native-with-sqlite-and-fp-ts-20cf</link>
      <guid>https://dev.to/dgopsq/handling-migrations-in-react-native-with-sqlite-and-fp-ts-20cf</guid>
      <description>&lt;p&gt;Recently, in one of my side projects, I had to use &lt;a href="https://docs.expo.io/versions/latest/sdk/sqlite/" rel="noopener noreferrer"&gt;expo-sqlite&lt;/a&gt; to manage a small client-side database in a &lt;strong&gt;React Native&lt;/strong&gt; app, while using the awesome &lt;a href="https://github.com/gcanti/fp-ts" rel="noopener noreferrer"&gt;fp-ts&lt;/a&gt;. I don't know if I will ever be able to ship that app, but at least I'm gonna use the experience I earned in (I hope) a good way 🙂.&lt;/p&gt;

&lt;h2&gt;
  
  
  React Native and Expo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt; is a framework for mobile applications that uses &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;React&lt;/a&gt; as its engine, compiling it into native (yeah, &lt;em&gt;native&lt;/em&gt;) views. This means that you can write native mobile applications using JavaScript (🤢) and React (❤️). This is already awesome, but &lt;a href="https://expo.io/" rel="noopener noreferrer"&gt;Expo&lt;/a&gt; will bring all of this to another level. Expo is a set of tools written upon React Native that simplifies the development of cross-platform mobile applications providing features like: universal APIs for native elements (push notifications, camera, accelerometer, ...), over-the-air updates, an in-cloud build infrastructure, and much more!&lt;/p&gt;

&lt;h2&gt;
  
  
  The awesome fp-ts
&lt;/h2&gt;

&lt;p&gt;This last year in my day job I had to use Scala in a purely functional way, and because of that I finally started to look at TypeScript with a bit of disdain and contempt. I tried a lot of different stuff (such as Reason, ScalaJS and PureScript) but I always found something I didn't like in each of them (although PureScript is still in my "evaluation list", since I'm not yet finished with it). The real game changer though was &lt;strong&gt;fp-ts&lt;/strong&gt;, which allowed me to use TypeScript in a &lt;em&gt;functional&lt;/em&gt; and &lt;em&gt;strongly-typed&lt;/em&gt; way, and since it's just Typescript I can use all the JavaScript APIs without bindings (and that's really great!). Sadly there are downsides too, TypeScript is not really FP-oriented, and a lot of features are a bit hack-y or just weird (like the &lt;a href="https://dev.to/gcanti/functional-design-algebraic-data-types-36kf"&gt;ADTs&lt;/a&gt;), but I have to say that giving it a bit of time it's still very enjoyable!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why migrations
&lt;/h2&gt;

&lt;p&gt;My app is 100% client side, and has a relatively small database (around 4 tables with 2 relations) that needs to be managed in run time. Why so? Because since it's completely client-side, whenever we have to add a feature that needs a database modification, we have to execute a SQL query directly on the app itself.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;right thing to do™&lt;/em&gt; is to have migrations, and there are different libraries that will help with them even on React Native (take a look at &lt;a href="https://typeorm.io/" rel="noopener noreferrer"&gt;TypeORM&lt;/a&gt;). A migration is a &lt;em&gt;tracked&lt;/em&gt; SQL query that will execute just one time on the target database. It's tracked because we have to know if the query has already been executed or not, and to do so we need a place to store the &lt;em&gt;current version&lt;/em&gt; of the database (or the already executed migrations).&lt;br&gt;
Let us begin with a small example to understand migrations: imagine to have an empty relational database, a little robot named Gigi with the job of &lt;em&gt;handling migrations&lt;/em&gt; and a list of SQL queries such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;V1__create_users_table.sql&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;V2__create_posts_table.sql&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;V3__create_comments_table.sql&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When we call Gigi, he'll start handling these migrations by checking his notebook for the last migration he executed on the database. In this first case he will notice that his notebook is empty, thus he will start executing all the migrations one-by-one, and at the end he's going to write that the last executed migration is &lt;code&gt;V3__create_comments_table.sql&lt;/code&gt;.&lt;br&gt;
The next day we add a &lt;code&gt;V4__delete_comments_table.sql&lt;/code&gt; query into the list, we call Gigi and he'll start the usual procedure, but this time he knows that he does't have to execute all the migrations again, but just the ones after &lt;code&gt;V3__create_comments_table.sql&lt;/code&gt;, so he starts executing the remaining SQL queries, and at the end he will replace the latest query in his notebook.&lt;/p&gt;

&lt;p&gt;This simple procedure allow us to have a &lt;strong&gt;versioned database&lt;/strong&gt; really easy to update and manage even when we don't really have a direct access (and this is our case!). What we are going to do here is &lt;em&gt;implement this feature from scratch using fp-ts&lt;/em&gt; with the advantage of an FP implementation and a light codebase (libraries like TypeORM are quite big sometimes 😕).&lt;/p&gt;
&lt;h2&gt;
  
  
  Expo SQLite and the Storage algebra
&lt;/h2&gt;

&lt;p&gt;Before writing the implementation of our migrations we need a bit of background! One of the many modules that Expo makes available to us is &lt;a href="https://docs.expo.io/versions/latest/sdk/sqlite/" rel="noopener noreferrer"&gt;expo-sqlite&lt;/a&gt;, which is a mobile implementation of an SQLite database. The usage is quite simple (although I struggled a bit to understand where actually was the database file created inside the simulator 😾) but I didn't like so much the APIs. For this reason I wrote a simple &lt;a href="https://typelevel.org/blog/2019/02/06/algebraic-api-design.html" rel="noopener noreferrer"&gt;&lt;em&gt;Algebra&lt;/em&gt;&lt;/a&gt; (which is an abstract collection of functions and values, if you are coming from the &lt;em&gt;Object Oriented Programming&lt;/em&gt; you can think of it as an &lt;em&gt;Interface&lt;/em&gt;) to "wrap" them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IStorageAlgebra&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/**
   * Execute a query to retrieve some value from
   * the db
   */&lt;/span&gt;
  &lt;span class="nl"&gt;retrieveQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;decoder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Decoder&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;QueryArgument&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DatabaseError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * Execute a query which does not obtain values
   */&lt;/span&gt;
  &lt;span class="nx"&gt;executeQuery&lt;/span&gt;&lt;span class="p"&gt;:&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;QueryArgument&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DatabaseError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * Execute multiple queries in a single transaction
   */&lt;/span&gt;
  &lt;span class="nx"&gt;executeQueriesInTransaction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;argsList&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;QueryArgument&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DatabaseError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * Setup the database
   */&lt;/span&gt;
  &lt;span class="nx"&gt;setup&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;TaskEither&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DatabaseError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;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 we need to explain something! The first thing you can notice is that every function returns a &lt;a href="https://gcanti.github.io/fp-ts/modules/TaskEither.ts.html" rel="noopener noreferrer"&gt;TaskEither&lt;/a&gt;. In fp-ts a &lt;code&gt;TaskEither&amp;lt;E, A&amp;gt;&lt;/code&gt; is a &lt;em&gt;Monad&lt;/em&gt; for handling asynchronous computations, it is the representation of a &lt;em&gt;Promise&lt;/em&gt; yielding &lt;code&gt;A&lt;/code&gt; as the successful result, and &lt;code&gt;E&lt;/code&gt; as the error. The second thing is the &lt;a href="https://github.com/gcanti/io-ts/blob/master/Decoder.md" rel="noopener noreferrer"&gt;Decoder&lt;/a&gt; which is not inside fp-ts but in another library called &lt;a href="https://gcanti.github.io/io-ts/" rel="noopener noreferrer"&gt;io-ts&lt;/a&gt;, this is just a module that allows us to type-check and "decode" a normal (and unknown) JavaScript object into something we actually know (If we have a &lt;code&gt;const myDecoder = Decoder&amp;lt;IMyObject&amp;gt;&lt;/code&gt;, we can do a &lt;code&gt;myDecoder.decode(unknownObj)&lt;/code&gt; to obtain a valid &lt;code&gt;IMyObject&lt;/code&gt; or an error otherwise).&lt;/p&gt;

&lt;p&gt;What we are going to do now is implement the &lt;code&gt;setup&lt;/code&gt; function, which will be executed at every startup of the application and has the task of bootstrapping the database and/or apply eventual updates (migrations!).&lt;/p&gt;

&lt;h2&gt;
  
  
  The migrations manager
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;setup&lt;/code&gt; function is what we precedently called "Migration manager". This function is divided into three main parts: &lt;strong&gt;Bootstrap&lt;/strong&gt;, &lt;strong&gt;Check&lt;/strong&gt;, and &lt;strong&gt;Execution&lt;/strong&gt;. Before delving deeper we should point out how the list of migrations is implemented inside this project:&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;sqliteMigrations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ISQLiteMigrations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`CREATE TABLE IF NOT EXISTS articles (
        id INTEGER PRIMARY KEY,
        title TEXT NOT NULL,
        body TEXT NOT NULL
      );`&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;Quite simple, isn't it? It's just a JavaScript object with the version number as the key, and the query to execute as the value.&lt;/p&gt;

&lt;p&gt;Now that we know how the migrations are structured, let's analyse the &lt;code&gt;setup&lt;/code&gt; function!&lt;/p&gt;

&lt;h3&gt;
  
  
  Bootstrap
&lt;/h3&gt;

&lt;p&gt;In the &lt;em&gt;Bootstrap&lt;/em&gt; we are merely creating the &lt;code&gt;__migration&lt;/code&gt; table (the place in which we are going to store the executed migrations) if it's not already present, and we are retrieving the last executed migration. The code for this part is quite simple:&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
  CREATE TABLE IF NOT EXISTS __migrations (
    id INTEGER PRIMARY KEY NOT NULL,
    version INTEGER NOT NULL,
    executed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
  )
`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is going to create a &lt;code&gt;__migrations&lt;/code&gt; table with an &lt;code&gt;id&lt;/code&gt; column, a &lt;code&gt;version&lt;/code&gt; (just a number to identify the migration) and the &lt;code&gt;executed_at&lt;/code&gt; which is the migration's execution timestamp. Now that we are sure a table exists, we need to retrieve the last migration executed:&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;// Decoder that represents a single migration&lt;/span&gt;
&lt;span class="nx"&gt;migrationsDecoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Decoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Decoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Decoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;executed_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Decoder&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="c1"&gt;// ...&lt;/span&gt;

&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieveQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;migrationsDecoder&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="s2"&gt;`
  SELECT * FROM __migrations ORDER BY id DESC LIMIT 1;
`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Check
&lt;/h3&gt;

&lt;p&gt;At this point we need to &lt;em&gt;Check&lt;/em&gt; the migrations to execute (if any) using the last migration retrieved. For this task we are going to create a specific helper function named &lt;code&gt;getUnexecutedMigrations&lt;/code&gt; that takes all the migrations plus an optional last migration, and returns a list of unexecuted migrations:&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;private&lt;/span&gt; &lt;span class="nx"&gt;getUnexecutedMigrations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ISQLiteMigrations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;maybeLastMigration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ordNumber&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;migrationsVersions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;maybeLastMigration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;Option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fold&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;migrationsVersions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastMigration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dropLeft&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;migrationsVersions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastMigration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;
              &lt;span class="nx"&gt;migrationsVersions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's worth noting that &lt;code&gt;Array&lt;/code&gt;, &lt;code&gt;Option&lt;/code&gt; and &lt;code&gt;pipe&lt;/code&gt; are all modules / functions contained into fp-ts. &lt;code&gt;Array&lt;/code&gt; is just a convenient FP way to handle native JavaScript arrays, &lt;code&gt;Option&lt;/code&gt; is the monad that handle the effect of optionality (the &lt;code&gt;Maybe&lt;/code&gt; in &lt;a href="https://wiki.haskell.org/Maybe" rel="noopener noreferrer"&gt;Haskell&lt;/a&gt;) and &lt;code&gt;pipe&lt;/code&gt; is just an helper to chain functions from left to right.&lt;/p&gt;

&lt;h3&gt;
  
  
  Execution
&lt;/h3&gt;

&lt;p&gt;The last section to analyse is the &lt;em&gt;Execution&lt;/em&gt;. Here, as the name probably suggests, we are going to execute all the remaining migrations. For each migration executed we need to add a line into the &lt;code&gt;__migrations&lt;/code&gt; table, so it's important to execute both queries in a single transaction, to assure the database consistency:&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;// Here we are managing the array of non-executed&lt;/span&gt;
&lt;span class="c1"&gt;// migrations inside a `pipe`, so the fist parameter&lt;/span&gt;
&lt;span class="c1"&gt;// of this `Array.map` is an `Array&amp;lt;number&amp;gt;`&lt;/span&gt;
&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;version&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeQueriesInTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="s2"&gt;`INSERT INTO __migrations (version, executed_at) VALUES (?, CURRENT_TIMESTAMP)`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[[],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;version&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;Taking a look at &lt;code&gt;IStorageAlgebra&lt;/code&gt; we can see that &lt;code&gt;executeQueriesInTransaction&lt;/code&gt; returns a &lt;code&gt;TaskEither&amp;lt;DatabaseError, void&amp;gt;&lt;/code&gt;, thus here we are just mapping an &lt;code&gt;Array&amp;lt;number&amp;gt;&lt;/code&gt; into an &lt;code&gt;Array&amp;lt;TaskEither&amp;lt;DatabaseError, void&amp;gt;&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The complete function
&lt;/h3&gt;

&lt;p&gt;This is the final &lt;code&gt;setup&lt;/code&gt; function:&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;public&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IDatabaseError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
      CREATE TABLE IF NOT EXISTS __migrations (
        id INTEGER PRIMARY KEY NOT NULL,
        version INTEGER NOT NULL,
        executed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
      )
    `&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chain&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieveQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;migrationsDecoder&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="s2"&gt;`
        SELECT * FROM &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;migrationsTable&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; ORDER BY id DESC LIMIT 1;
      `&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;executedMigrations&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;executedMigrations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;m&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;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUnexecutedMigrations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;version&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeQueriesInTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;
              &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;migrations&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
              &lt;span class="s2"&gt;`INSERT INTO &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;migrationsTable&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (version, executed_at) VALUES (?, CURRENT_TIMESTAMP)`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;[[],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;version&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="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sequence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taskEither&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nx"&gt;TaskEither&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the explained parts are joined through a &lt;code&gt;pipe&lt;/code&gt; with &lt;code&gt;TaskEither.chain&lt;/code&gt; as the "link". Since &lt;code&gt;TaskEither&lt;/code&gt; is a monad we can compose it using its &lt;code&gt;flatmap&lt;/code&gt; function (which is just renamed here into &lt;code&gt;chain&lt;/code&gt;). The last two functions are a bit obscure: &lt;code&gt;Array.array.sequence(TaskEither.taskEither)&lt;/code&gt; takes an &lt;code&gt;Array&amp;lt;TaskEither&amp;lt;E, A&amp;gt;&amp;gt;&lt;/code&gt; and returns a &lt;code&gt;TaskEither&amp;lt;E, Array&amp;lt;A&amp;gt;&amp;gt;&lt;/code&gt;. We are using it to "merge" all the successful results of the various async computations into a single &lt;code&gt;TaskEither&lt;/code&gt; that we are going to &lt;code&gt;map&lt;/code&gt; into an &lt;code&gt;undefined&lt;/code&gt; because we don't actually need any result.&lt;/p&gt;

&lt;p&gt;That's all! 🙋‍♂️&lt;/p&gt;

</description>
      <category>functional</category>
      <category>reactnative</category>
      <category>expo</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
