<?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: Alexandre</title>
    <description>The latest articles on DEV Community by Alexandre (@asantos00).</description>
    <link>https://dev.to/asantos00</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%2F3664%2F27c0b87f-4c6f-4547-b376-ca1a5ad5d774.png</url>
      <title>DEV Community: Alexandre</title>
      <link>https://dev.to/asantos00</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/asantos00"/>
    <language>en</language>
    <item>
      <title>I published a book - Deno Web Development 🦕</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Thu, 01 Apr 2021 11:42:01 +0000</pubDate>
      <link>https://dev.to/asantos00/i-published-a-book-deno-web-development-3oja</link>
      <guid>https://dev.to/asantos00/i-published-a-book-deno-web-development-3oja</guid>
      <description>&lt;p&gt;As some of you might know, I've been working on something for the last six months -- a book! &lt;/p&gt;

&lt;p&gt;Presenting &lt;a href="https://www.amazon.com/gp/product/180020566X" rel="noopener noreferrer"&gt;Deno Web Development&lt;/a&gt;, a book about &lt;a href="https://deno.land" rel="noopener noreferrer"&gt;Deno&lt;/a&gt;, a secure runtime for JavaScript and TypeScript, and how to use it for web development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Falexandrempsantos.com%2Fstatic%2F5e36fad10189bbc0f9755ec12523ea43%2F566ce%2Fdeno-new.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Falexandrempsantos.com%2Fstatic%2F5e36fad10189bbc0f9755ec12523ea43%2F566ce%2Fdeno-new.png" alt="deno-web-development"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The book focuses on how you can write, test, maintain, and deploy JavaScript and TypeScript web applications using Deno. &lt;/p&gt;

&lt;h2&gt;
  
  
  The approach
&lt;/h2&gt;

&lt;p&gt;It is a guided journey discovering this new runtime, understanding the reasons for its creation, what problems it solves, and how to use it to build a real-world application. &lt;/p&gt;

&lt;p&gt;The book starts with "hello world" and finishes with an API deployed in a cloud environment. In the meantime, it covers topics such as dependency and configuration management, connecting with the database, structuring an application, testing, among many others. &lt;/p&gt;

&lt;h2&gt;
  
  
  What to expect
&lt;/h2&gt;

&lt;p&gt;By the end of "Deno Web Development", the reader will have all the knowledge to decide whether to use Deno in their next project. &lt;/p&gt;

&lt;p&gt;As the book progresses, the reader will get to know the ups and downsides of the technology, not only because they're listed there, but also because they'll experience them as they build an application from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  The audience
&lt;/h2&gt;

&lt;p&gt;I tried to make the book approachable as an introduction to the technology but audacious enough to include many engineering best practices. &lt;/p&gt;

&lt;p&gt;"Deno Web Development" targets people with JavaScript knowledge that want to know more about Deno, understanding how to use it to solve common industry challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Special thanks
&lt;/h2&gt;

&lt;p&gt;Publishing the book wouldn't be possible without the opportunity offered to me by &lt;a href="https://www.packtpub.com/" rel="noopener noreferrer"&gt;Packt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same applies to my friends: Felipe, Gonçalo, Bruno, Nuno, János, João, and Miguel. Writing this book wouldn't be possible without your help. Thank you for always being available to discuss a variety of topics and providing meaningful feedback. You're the best! 🙏&lt;/p&gt;

&lt;p&gt;And of course, my family and friends for how they encouraged me to follow this "adventure" of joining two of my passions: technology and writing, and writing a book.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where can I buy it?
&lt;/h2&gt;

&lt;p&gt;The book is now available globally, on &lt;a href="https://www.amazon.com/gp/product/180020566X" rel="noopener noreferrer"&gt;Amazon&lt;/a&gt; in Kindle and paperback versions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/gp/product/180020566X" rel="noopener noreferrer"&gt;https://www.amazon.com/gp/product/180020566X&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.de/gp/product/180020566X" rel="noopener noreferrer"&gt;https://www.amazon.de/gp/product/180020566X&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.es/gp/product/180020566X" rel="noopener noreferrer"&gt;https://www.amazon.es/gp/product/180020566X&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.co.uk/gp/product/180020566X" rel="noopener noreferrer"&gt;https://www.amazon.co.uk/gp/product/180020566X&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'd be happy to hear any feedback you have about it, so feel free to reach out to me if you have any questions about it.&lt;/p&gt;

&lt;p&gt;If you're curious, I'm thinking of writing a little more on how was the experience of writing the book in the following weeks, adding to what I already said on a previous &lt;a href="https://authors.packtpub.com/interview-with-alexandre-portela-dos-santos/" rel="noopener noreferrer"&gt;interview&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thank you&lt;/p&gt;

</description>
      <category>deno</category>
      <category>node</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
    <item>
      <title>Second adventure in deno land</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Tue, 13 Oct 2020 00:01:00 +0000</pubDate>
      <link>https://dev.to/asantos00/second-adventure-in-deno-land-3jbl</link>
      <guid>https://dev.to/asantos00/second-adventure-in-deno-land-3jbl</guid>
      <description>&lt;p&gt;On my last post, I wrote about &lt;a href="https://alexandrempsantos.com/adventures-in-deno-land/"&gt;my first adventure in deno.land&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It was a fun one, the excitement of trying some new technology was always there. &lt;em&gt;deno&lt;/em&gt; left me thinking about new possibilities and asking myself what am I going to build with it.&lt;/p&gt;

&lt;p&gt;Last time around I have built a small twitter bot in order to scratch the surface of the standard library and to get to know &lt;em&gt;deno&lt;/em&gt; a little better in deeper context than a simple "hello world".&lt;/p&gt;

&lt;p&gt;It was very well-received, way more than what I was expecting. It ended up being, at the time, my most read and reacted post ever. I guess I got quite lucky on the "&lt;em&gt;deno&lt;/em&gt; hype train".&lt;/p&gt;

&lt;p&gt;Back to what brought me here today. After exploring the standard library, module imports, simple permission system and dependency management, today I'll explore the following topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lock files&lt;/li&gt;
&lt;li&gt;Official VSCode extension&lt;/li&gt;
&lt;li&gt;Documentation generation&lt;/li&gt;
&lt;li&gt;Permission system&lt;/li&gt;
&lt;li&gt;Running &lt;em&gt;deno&lt;/em&gt; code in the browser&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to follow the code, &lt;a href="https://github.com/asantos00/deno-twitter-popular"&gt;here you have it&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lock files
&lt;/h2&gt;

&lt;p&gt;To complete the information from the last post about dependencies, I'll write about lock files. They're a standard practice in many languages in pretty much every production app. They're used to describe an exact tree of dependencies, in order to make installations more repeatable, avoiding issues that may arise out of version misalignement.&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;deno&lt;/em&gt; you can generate a lock file for the used dependencies by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;deno cache &lt;span class="nt"&gt;--lock&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lock.json &lt;span class="nt"&gt;--lock-write&lt;/span&gt; ./src/deps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This command will &lt;em&gt;cache&lt;/em&gt; (that local installs the used dependencies) based on a &lt;code&gt;lock.json&lt;/code&gt; file. The &lt;code&gt;--lock-write&lt;/code&gt; flag updates or creates the &lt;code&gt;lock.json&lt;/code&gt; file. The last parameter is the file that uses the dependencies.&lt;/p&gt;

&lt;p&gt;To install the dependencies while integrity checking every installed resource, one can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;deno cache &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--lock&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lock.json deps.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://github.com/asantos00/deno-twitter-popular/blob/master/lock.json"&gt;generated file&lt;/a&gt; is nothing more than a json object of dependencies and its checksum&lt;/p&gt;

&lt;h2&gt;
  
  
  Official VSCode extension
&lt;/h2&gt;

&lt;p&gt;The official vscode extension has been launched! However, it is the exact same that I have mentioned on my previous post. It simply got moved to the official repo, as the changelog states&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Moved from &lt;a href="https://github.com/justjavac/vscode-deno"&gt;https://github.com/justjavac/vscode-deno&lt;/a&gt; to &lt;a href="https://github.com/denoland/vscode_deno"&gt;https://github.com/denoland/vscode_deno&lt;/a&gt; in order to have an "official" Deno plugin.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It works very well, autocompletes and files imports are fine, as expected. There's a small problem though, when you cmd + click on external dependencies, it does not detect the language, so the file appears without any highlighting.&lt;/p&gt;

&lt;p&gt;I'm sure it will be fixed soon but it's also a good &lt;strong&gt;oportunity for contribution&lt;/strong&gt; that I might take, after I get the time to understand the code from vscode and the plugin itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation
&lt;/h2&gt;

&lt;p&gt;Another of the advantages presented by Ryan in his talk was that deno included a documentation generator on its toolchain. It doesn't have (yet) a section on the website, but we'll explore it a bit here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Browse modules documentation
&lt;/h3&gt;

&lt;p&gt;Even though deno has no &lt;code&gt;install&lt;/code&gt; step, the &lt;code&gt;cache&lt;/code&gt; lets you develop in an airplane (as you did with &lt;code&gt;node_modules&lt;/code&gt;), as it loads the modules the first time and then uses the cached one.&lt;/p&gt;

&lt;p&gt;While working on an airplane, what if you want to look at third party code docs? You can use your editor of choice, yes, but there's an alterantive.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;deno&lt;/em&gt; provides a cool way to see the third party code documentation without having to browse the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;deno doc https://deno.land/std/http/server.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This outputs the methods exposed by the standard library's http server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;listenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr&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;|&lt;/span&gt; &lt;span class="nx"&gt;HTTPOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ServerRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="nx"&gt;Start&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;HTTP&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;given&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;listenAndServeTLS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTTPSOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ServerRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="nx"&gt;Start&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;HTTPS&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;given&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr&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;|&lt;/span&gt; &lt;span class="nx"&gt;HTTPOptions&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Server&lt;/span&gt;
  &lt;span class="nx"&gt;Create&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;HTTP&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;serveTLS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTTPSOptions&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Server&lt;/span&gt;
  &lt;span class="nx"&gt;Create&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;HTTPS&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;given&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Server&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;AsyncIterable&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ServerRequest&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;
  &lt;span class="nx"&gt;Interface&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;HTTP&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;If&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="nx"&gt;would&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;chunked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;If&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;a&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;it&lt;/span&gt; &lt;span class="nx"&gt;would&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;UTF&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="nx"&gt;encoded&lt;/span&gt; &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;HTTPOptions&lt;/span&gt;
  &lt;span class="nx"&gt;Options&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;creating&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;HTTP&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;HTTPSOptions&lt;/span&gt;
  &lt;span class="nx"&gt;Options&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;creating&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;HTTPS&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Very neat, right? A very nice way of having an overview of the modules exported symbols.&lt;/p&gt;

&lt;p&gt;To see the documentation for a specific symbol, one can also run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;deno doc https://deno.land/std/http/server.ts listenAndServe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Which outputs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;listenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr&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;|&lt;/span&gt; &lt;span class="nx"&gt;HTTPOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ServerRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="nx"&gt;Start&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;HTTP&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;given&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;     &lt;span class="nx"&gt;listenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;       &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respond&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;body&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="nd"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="nx"&gt;Server&lt;/span&gt; &lt;span class="nx"&gt;configuration&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;param&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;

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



&lt;p&gt;You can use the documentation command to have an overview of your code's exported modules, it works the same way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;deno doc twitter/client.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="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;search&lt;/span&gt;
  &lt;span class="nx"&gt;Searches&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;recent&lt;/span&gt; &lt;span class="nx"&gt;tweets&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;provided&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;have&lt;/span&gt; &lt;span class="nx"&gt;more&lt;/span&gt; &lt;span class="nx"&gt;than&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="nx"&gt;likes&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Tweet&lt;/span&gt;
  &lt;span class="nx"&gt;Fields&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;tweet&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;TweetResponse&lt;/span&gt;
  &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;Twitter&lt;/span&gt; &lt;span class="nx"&gt;API&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--json&lt;/code&gt; flag is also supported (however, not for symbols), and allows generating the documentation in the json format, enabling programmatic uses.&lt;/p&gt;

&lt;p&gt;One great example of the documentation generation uses is &lt;em&gt;deno&lt;/em&gt; &lt;a href="https://doc.deno.land/https/github.com/denoland/deno/releases/latest/download/lib.deno.d.ts"&gt;runtime API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It uses Deno to generate modules with the &lt;code&gt;--json&lt;/code&gt; command and provides a really nice layout around it. We just needed to add &lt;code&gt;typedoc&lt;/code&gt; to our modules, like what we did &lt;a href="https://github.com/asantos00/deno-twitter-popular/commit/dbac72b58f46ace067381cbdfc5708877b033aac#diff-8575744caf69ee401aa128c0f0d46a42R71"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fine grained permissions
&lt;/h2&gt;

&lt;p&gt;As we talked &lt;a href="https://alexandrempsantos.com/adventures-in-deno-land/"&gt;on my previous post&lt;/a&gt;, one thing that &lt;em&gt;deno&lt;/em&gt; got very well were permissions. They're easy to use and secure by default. Previously, I've explained that in order for a script to be able to access the network, for instance, you'd have to explicitly use &lt;code&gt;--allow-net&lt;/code&gt; flag when running it.&lt;/p&gt;

&lt;p&gt;That is true, however, I was alerted by my friend &lt;a href="https://twitter.com/schmittfelipe"&gt;Felipe Schmitt&lt;/a&gt; that in order for it to be stricter, we can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deno run --allow-net=api.twitter.com,0.0.0.0 index.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will, as you probably guessed, allow network calls to &lt;code&gt;api.twitter.com&lt;/code&gt; and from &lt;code&gt;0.0.0.0&lt;/code&gt; but disallow all the other calls. Instead of allowing complete access to network, we're allowing just part of it, whitelisting and blocking everything else by default.&lt;/p&gt;

&lt;p&gt;This is now very well explained on the &lt;a href="https://deno.land/manual/getting_started/permissions"&gt;Permissions page&lt;/a&gt;, which is one of the documentation improvements that were added after the v.1.0.0 launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running code in the browser
&lt;/h2&gt;

&lt;p&gt;Another very interesting feature of &lt;em&gt;deno&lt;/em&gt;, is the &lt;code&gt;bundle&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;It allows us to bundle your code into a single &lt;code&gt;.js&lt;/code&gt; file. That file can be run as any other deno program, with &lt;code&gt;deno run&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What I find interesting is that the generated code, when it doesn't use the &lt;code&gt;Deno&lt;/code&gt; namespace, is that it &lt;strong&gt;can run on the browser&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The possibilities for this are limitless. For instance, what if I wanted my API to generate an HTTP client for frontends to interact with it?&lt;/p&gt;

&lt;p&gt;We can write that client in &lt;em&gt;deno&lt;/em&gt;, reusing API code (and types). Here's the code to get the popular tweets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TweetResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../twitter/client.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;popular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handle&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TweetResponse&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`http://localhost:8080/popular/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;handle&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="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/asantos00/deno-twitter-popular/blob/master/client/index.ts"&gt;Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This code lives on the API codebase and it is written in &lt;em&gt;deno&lt;/em&gt;. It uses the same types from the twitter client the API uses.&lt;/p&gt;

&lt;p&gt;Having the API client living on the API codebase means that whoever updates the API can also update the client, abstracting the backend and API changes from the frontend code. This is not a &lt;em&gt;deno&lt;/em&gt; feature but something that it enables via this bundling feature.&lt;/p&gt;

&lt;p&gt;Then, we can run the &lt;code&gt;bundle&lt;/code&gt; command and put the generated file in a folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;deno bundle client/index.ts public/client.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It will generate the &lt;code&gt;client.js&lt;/code&gt; file that can run on the browser.&lt;/p&gt;

&lt;p&gt;For demonstration purposes we can create a &lt;code&gt;public/index.html&lt;/code&gt; file with the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c1"&gt;// Imports the generated client&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./client.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fetchTwitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Uses the methods on it&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;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;popular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="cm"&gt;/*
      Omitted for brevity
    */&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/asantos00/deno-twitter-popular/blob/master/public/index.html"&gt;Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This code uses client that was initially written in &lt;em&gt;deno&lt;/em&gt;, and is now a js file.&lt;/p&gt;

&lt;p&gt;Now, this &lt;code&gt;public&lt;/code&gt; folder can be served by any webserver. Since we're talking about &lt;em&gt;deno&lt;/em&gt;, we can take advantage of it and serve the files with standard library's file server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# inside the public folder&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;deno run &lt;span class="nt"&gt;--allow-net&lt;/span&gt; &lt;span class="nt"&gt;--allow-read&lt;/span&gt; https://deno.land/std/http/file_server.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can now visit &lt;code&gt;http://0.0.0.0:4507/&lt;/code&gt; and use our very archaic frontend to query for popular tweets. With this, our code can use the client that was &lt;strong&gt;originally written in deno&lt;/strong&gt; on the frontend, to interact with the API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n_PDzMNO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/v1/./second-adventure-in-deno-land/deno_tweets.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n_PDzMNO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/v1/./second-adventure-in-deno-land/deno_tweets.png" alt="deno_tweets"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Following &lt;em&gt;deno&lt;/em&gt;'s goal of shipping the essentials in a single binary, testing is obviously included. The documentation is, again, quite good on this. With the help of the &lt;code&gt;doc&lt;/code&gt; command, it gets very straight-forward to write tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;deno doc https://deno.land/std/testing/asserts.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This prints the documentation for the assert module from &lt;em&gt;deno&lt;/em&gt; standard library&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&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;UNIMPLEMENTED&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;Make&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;assertion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="s2"&gt;`true`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;then&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&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="k"&gt;void&lt;/span&gt;
  &lt;span class="nx"&gt;Make&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;assertion&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="s2"&gt;`actual`&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="s2"&gt;`expected`&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deeply&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;If&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;deeply&lt;/span&gt; &lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;then&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;assertMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actual&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;expected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&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="k"&gt;void&lt;/span&gt;
  &lt;span class="nx"&gt;Make&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;assertion&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="s2"&gt;`actual`&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt; &lt;span class="s2"&gt;`expected`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;If&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;then&lt;/span&gt; &lt;span class="nx"&gt;thrown&lt;/span&gt;

&lt;span class="cm"&gt;/* Cut for brevity */&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&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="k"&gt;void&lt;/span&gt;
  &lt;span class="nx"&gt;Forcefully&lt;/span&gt; &lt;span class="nx"&gt;throws&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;failed&lt;/span&gt; &lt;span class="nx"&gt;assertion&lt;/span&gt;

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



&lt;p&gt;Let's write a simple test to our "isomorphic" client we created a few lines above.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Deno.test&lt;/code&gt; will be used to declare the test body, &lt;code&gt;assertEquals&lt;/code&gt; will be called to make the assertion. In order to mock the server responses, we'll spin up a server using standard-library &lt;em&gt;http_server&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;We expect that, the &lt;code&gt;popular&lt;/code&gt; method from the client calls &lt;code&gt;/popular/:twitterHandle&lt;/code&gt;. Let's create a test for that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ApiClient&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;assertEquals&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../deps.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;runServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../util.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;calls the correct url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&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;runServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;req&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;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/popular/ampsantos0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respond&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;statuses&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ApiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;popular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ampsantos0&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;&lt;a href="https://github.com/asantos00/deno-twitter-popular/blob/master/client/index.test.ts"&gt;Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;runServer&lt;/code&gt; util is a very simple function that just spawns a web server that closes after the first connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ServerRequest&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./deps.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;runServer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ServerRequest&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;Promise&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;:8080&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await&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;req&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="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;&lt;a href="https://github.com/asantos00/deno-twitter-popular/blob/master/util.ts"&gt;Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can now run the test. Remember that everytime we run a &lt;em&gt;deno&lt;/em&gt; program we need to pass the permission flags.&lt;/p&gt;

&lt;p&gt;It will run as test every file matching the following regex &lt;code&gt;{*_,*.,}test.{js,ts,jsx,tsx}:&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLDR&lt;/strong&gt;: It runs every file that has &lt;code&gt;test&lt;/code&gt; in its name and ends with one of the mentioned file extensions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;deno &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--allow-net&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If the test is failing, we're presented with a nice diff.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="nx"&gt;calls&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;correct&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Uncaught&lt;/span&gt; &lt;span class="nx"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Values&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Diff&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="nx"&gt;Actual&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;Expected&lt;/span&gt;


&lt;span class="o"&gt;-&lt;/span&gt;   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/popular/ampsantos0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;   &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/popular/handle-that-doesnt-work&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;^&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;assertEquals&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//deno.land/std/testing/asserts.ts:170:9)&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;///Users/alexandre/dev/personal/deno/testing-deno/client/index.test.ts:7:5&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;runServer&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;///Users/alexandre/dev/personal/deno/testing-deno/util.ts:9:11)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In order to run just part of the tests, the &lt;code&gt;--filter&lt;/code&gt; flag can be used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;deno &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--allow-net&lt;/span&gt; &lt;span class="nt"&gt;--filter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"correct url"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And a path can also be sent as the last argument&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;deno &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--allow-net&lt;/span&gt; ./client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can follow all the listed changes related to tests on &lt;a href="https://github.com/asantos00/deno-twitter-popular/commit/14b7a623ac84d689f9e9872685b93cd6bd138a9c"&gt;this commit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And with this, we have pretty much everything we need in order to write compreensive tests. Again, the essentials are there, we can (and probably will) create a couple more test utilities composing on top of the standard library, but for simple tests as the one we just wrote, this is enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;On our second adventure, we went a little further than just presenting the language.&lt;/p&gt;

&lt;p&gt;We explored some other parts of the runtime. From testing, generating documentation, lock files, stricter permissions, to generating javascript code and running it on the client. All of them are features we considered useful when writing &lt;em&gt;production&lt;/em&gt; code. We let benchmarks out for the next adventure 😉.&lt;/p&gt;

&lt;p&gt;We can't forget that we did all of this with the toolset that is &lt;strong&gt;included&lt;/strong&gt; in &lt;em&gt;deno&lt;/em&gt;, no libraries were used.&lt;/p&gt;

&lt;p&gt;This doesn't mean that developers will not use and write libraries. It means though that the standard library is very well written and easy to use. This opens the door for developers to write powerful, and meaningful abstractions on top of it.&lt;/p&gt;

&lt;p&gt;Together with the standard library, the toolchain offered with the main binary proves itself very complete, aligned the goal of &lt;em&gt;Only ship a single executable&lt;/em&gt;, mentioned on &lt;em&gt;deno&lt;/em&gt; docs. I'd say all the essentials are there and you don't have to worry about tooling.&lt;/p&gt;

&lt;p&gt;This adventure took a little longer that expected. Thanks for reading it.&lt;/p&gt;

&lt;p&gt;I hope it was as fun reading as it was for me exploring it. I'd love to hear what you have to say about it and answer all the questions you might have.&lt;/p&gt;

</description>
      <category>deno</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
    <item>
      <title>Adventures in deno land</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Mon, 12 Oct 2020 23:57:56 +0000</pubDate>
      <link>https://dev.to/asantos00/adventures-in-deno-land-1mi7</link>
      <guid>https://dev.to/asantos00/adventures-in-deno-land-1mi7</guid>
      <description>&lt;p&gt;Earlier this year &lt;a href="https://deno.land/"&gt;deno&lt;/a&gt; was released.&lt;/p&gt;

&lt;p&gt;As I was very excited ever since I first heard about it on &lt;a href="https://youtu.be/M3BM9TB-8yA"&gt;Ryan Dahl's talk&lt;/a&gt; at &lt;a href="https://jsconf.eu"&gt;jsconf&lt;/a&gt;, I had to give it a try.&lt;/p&gt;

&lt;p&gt;This talk is one of my personal favorites, it is a lesson on humility.&lt;br&gt;
Having Ryan looking at what he built 10 years ago with a criticizing tone is interesting. Even when &lt;em&gt;node&lt;/em&gt; is used by millions of people, its creator still feels bad about some decisions made at the time.&lt;/p&gt;

&lt;p&gt;Getting back to what brought me here... After hearing of the launch of v1.0 I took some hours to learn more about it. The documentation is very well written and structured, which by following what they call &lt;em&gt;the manual&lt;/em&gt; one could have a very good understanding of how to start using it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Building something
&lt;/h2&gt;

&lt;p&gt;After reading the documentation, it looked great, in theory. But my default way to learn is normally to &lt;em&gt;build something with it&lt;/em&gt;. It normally helps me identify pains I'd have in the real world if I had to build a &lt;em&gt;real&lt;/em&gt; application with it.&lt;/p&gt;

&lt;p&gt;The decision was to &lt;strong&gt;build an API that connects to twitter&lt;/strong&gt; and returns 15 tweets from a user with more than 5 likes, I called it &lt;em&gt;popular tweets&lt;/em&gt;. This small server should then run on a Kubernetes environment.&lt;/p&gt;

&lt;p&gt;If you wanna follow the code, &lt;a href="https://github.com/asantos00/deno-twitter-popular"&gt;here you have it&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first, I was kinda lost and didn't know any APIs. I've decided to go explore the &lt;a href="https://deno.land/std"&gt;standard library&lt;/a&gt;. I got very impressed by how approachable was the code, took some time to read it, and learned a ton.&lt;/p&gt;

&lt;p&gt;It got this idea on the back of my mind, which might lead to a future article, similar to what &lt;a href="https://twitter.com/paul_irish"&gt;Paul Irish&lt;/a&gt; did 10 years ago on &lt;a href="https://www.paulirish.com/2010/10-things-i-learned-from-the-jquery-source/"&gt;10 things I learned from the jquery source&lt;/a&gt; but for deno source, might actually do it!&lt;/p&gt;

&lt;p&gt;After getting to know the basics, installing the &lt;a href="https://marketplace.visualstudio.com/items?itemName=justjavac.vscode-deno"&gt;VSCode plugin&lt;/a&gt; and deno, we were ready to start my adventure.&lt;/p&gt;

&lt;p&gt;To be honest, &lt;em&gt;it wasn't a real adventure&lt;/em&gt;, everything looked so familiar that I almost forgot I was using a different runtime.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting to code
&lt;/h2&gt;

&lt;p&gt;By using the standard library's &lt;code&gt;http server&lt;/code&gt; it was very easy to build a server and get it up running handling requests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./deps.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await&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;req&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;respond&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello world&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Step 2 was to connect it to twitter API. Having &lt;code&gt;fetch&lt;/code&gt; already included on &lt;code&gt;deno&lt;/code&gt; made it very easy and familiar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.twitter.com/1.1/search/tweets.json&amp;amp;q=(from: ampsantos0 min_faves: 5)&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="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content-type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Deno opted for mimicking existing Web APIs where they existed, rather than inventing new proprietary ones. For APIs that are not web standard, the &lt;code&gt;Deno&lt;/code&gt; namespace is used. This looks like a smart choice to me, improving discoverability and reusing knowledge developers already have of the existing APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running it
&lt;/h2&gt;

&lt;p&gt;Running the code was a breeze. One of deno's selling points is security and I couldn't agree more, it improved over &lt;em&gt;node&lt;/em&gt;. You notice it the first time you try to run a program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;deno run ./index.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once we are, in this case, using network to both expose our &lt;strong&gt;endpoint&lt;/strong&gt; (:8080) and access &lt;strong&gt;Twitter's API&lt;/strong&gt; without our explicit consent, here's what you get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error: Uncaught PermissionDenied: network access to "0.0.0.0:8080", run again with the --allow-net flag
    at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11)
    at Object.sendSync ($deno$/ops/dispatch_json.ts:72:10)
    at Object.listen ($deno$/ops/net.ts:51:10)
    at listen ($deno$/net.ts:152:22)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is a very reasonable and comprehensive error, again, good job on this!&lt;/p&gt;

&lt;p&gt;A good approach for this is by enabling whitelist permissions by using the flag &lt;code&gt;--allow-net&lt;/code&gt; which deno does it in a very simple and pragmatic way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;deno run &lt;span class="nt"&gt;--allow-net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.0.0.0:8080,api.twitter.com index.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When running the code, the &lt;code&gt;--inspect&lt;/code&gt; flag enables developers to use Chrome Dev Tools the same way they did in &lt;em&gt;node&lt;/em&gt;, the debugging experience is as good as developers are used to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Module resolution
&lt;/h2&gt;

&lt;p&gt;When Ryan first talked about deno, and the &lt;em&gt;mistakes made in node's design&lt;/em&gt;, one of the big things he mentioned that &lt;em&gt;node's&lt;/em&gt; way of importing modules was too complicated and had lots of edge cases.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The dependency we're importing, &lt;em&gt;path&lt;/em&gt; might come from &lt;em&gt;node&lt;/em&gt; standard library. At the same time, it can come from &lt;em&gt;node-modules&lt;/em&gt;, or you could have installed a dependency named &lt;em&gt;path&lt;/em&gt;, right? Ok, now you found the dependency, do you know what is the file you are requiring? Is it index.js? What if &lt;em&gt;package.json&lt;/em&gt; has a different &lt;em&gt;main&lt;/em&gt; file defined?&lt;/p&gt;

&lt;p&gt;Lots of unknowns...&lt;/p&gt;

&lt;p&gt;What about local imports? When you do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;add1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./utils/math&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Is &lt;code&gt;math&lt;/code&gt; a file? Or a folder with an &lt;code&gt;index.js&lt;/code&gt; inside of it? What is the file extension? Is it &lt;em&gt;.js&lt;/em&gt;, &lt;em&gt;.ts&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;You get the point... &lt;strong&gt;Node imports are hard&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Deno follows a &lt;code&gt;golang&lt;/code&gt; like approach, of having &lt;em&gt;absolute urls&lt;/em&gt;. If it sounds strange to you, bare with me. Let's look at the advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It solves local imports by adding the extension to it.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;add1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./utils/math.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You know just from reading it that &lt;code&gt;math.ts&lt;/code&gt; is a file.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It solves third party imports by having an absolute URL
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://deno.land/std/http/server.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;No more magic module resolution.&lt;/p&gt;

&lt;p&gt;This absolute module resolution enabled some fun stuff like what &lt;a href="https://twitter.com/ralex1993/status/1261039838100221952"&gt;R. Alex Anderson&lt;/a&gt; did, running code from a set of gists.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/ralex1993/status/1261039838100221952"&gt;https://twitter.com/ralex1993/status/1261039838100221952&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: VSCode plugin functions well with the third party imports, you can &lt;code&gt;cmd+click&lt;/code&gt; on dependency and you're directed to the code, as usual.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping track of dependencies
&lt;/h2&gt;

&lt;p&gt;Let's talk about managing dependencies. As &lt;em&gt;deno&lt;/em&gt; simplified the module imports, it allowed it to &lt;em&gt;automatically cache&lt;/em&gt; dependencies.&lt;/p&gt;

&lt;p&gt;When you first try to run it, it downloads the dependencies, caches them, and then runs with the cached version.&lt;/p&gt;

&lt;p&gt;To force the caching of a module without running it, you can run &lt;code&gt;$ deno cache [module url]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You are probably thinking it is strange and error-prone to URLs all around the code? That's right. You can manage it however you want, as all modules have absolute URLs now, it's just code at the end of the day.&lt;/p&gt;

&lt;p&gt;Deno recommends having a &lt;code&gt;deps.ts&lt;/code&gt; file, you can call it whatever you want but since it &lt;a href="https://deno.land/manual/linking_to_external_code#it-seems-unwieldy-to-import-urls-everywhere"&gt;is in the documentation&lt;/a&gt;, I see this start becoming a standard. On that file, you can import all the dependencies from the URLs and export the methods used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// deps.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://deno.land/std/http/server.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parseDate&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://deno.land/std/datetime/mod.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// index.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./deps.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Having one single &lt;code&gt;deps.ts&lt;/code&gt; file allows you to do some caching (as you did in &lt;code&gt;package.json&lt;/code&gt;) on docker builds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; deps.ts .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;deno cache deps.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By doing this, the &lt;code&gt;RUN&lt;/code&gt; command will only run if the &lt;code&gt;deps.ts&lt;/code&gt; file changed. With this, and as the installation step is now &lt;em&gt;automatic&lt;/em&gt;, running it on docker became simpler.&lt;/p&gt;

&lt;p&gt;There is one thing that has to be taken care of with deno, we have to send the flags for the permissions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["run", "--allow-net", "index.ts"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Deno binaries
&lt;/h2&gt;

&lt;p&gt;Deno provides an &lt;code&gt;install&lt;/code&gt; command. But, as I said earlier, it does not install dependencies on the project, as that is done automatically.&lt;/p&gt;

&lt;p&gt;Its usage is similar to the &lt;code&gt;npm install --global&lt;/code&gt; flag, citing the explanation on the official website about &lt;code&gt;install&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This command creates a thin, executable shell script which invokes deno using the specified CLI flags and main module. It is placed in the installation root's bin directory.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When you install a global binary, you have to specify what permissions it will need to run, again, secure by default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And you can then run &lt;code&gt;$ file_server&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;Coming from the JS/TS world I'd say deno got lots of things right. It has the familiarity of JS and TS with small twists, to the better side. Having the standard library written in TS is a big plus, at it isn't always straightforward to set it up in &lt;em&gt;node&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The standard library is great, it looks both readable and well thought. Quoting the &lt;code&gt;deno_std&lt;/code&gt; main repo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;deno_std is a loose port of Go's standard library. When in doubt, simply port Go's source code, documentation, and tests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is funny and interesting at the same time, deno used the effort the golang community put in its standard lib to drive its own, the result looks great.&lt;/p&gt;

&lt;p&gt;The permission system is great and intuitive. Module resolution is now simpler and removes pretty much all the magic we got used to in &lt;em&gt;node lands&lt;/em&gt;.&lt;br&gt;
All the async APIs return Promises now. It means using &lt;code&gt;await&lt;/code&gt; and &lt;code&gt;.then&lt;/code&gt; everywhere, not incurring into callback hell and not needing tools like &lt;code&gt;promisify&lt;/code&gt; and such.&lt;/p&gt;

&lt;p&gt;Adding to all of this, deno also got inspiration from golang by shipping a lot of the essential tools in the main binary. Discussions about bundler, formatter, and test runner will no longer be a thing, and even if they are, there's an official way now. I haven't tried the test suite and the documentation generator yet, I might write about it later.&lt;/p&gt;

&lt;p&gt;Gotta say the overall experience of building a (very small) application with it was very good and intuitive. Can't wait to build something more &lt;em&gt;real&lt;/em&gt; with it!&lt;/p&gt;

&lt;p&gt;I'm excited to see how this will evolve and thus I wrote another article, my &lt;a href="https://alexandrempsantos.com/second-adventure-in-deno-land/"&gt;second adventure in deno.land&lt;/a&gt; where I go a little deeper on the runtime.&lt;/p&gt;

</description>
      <category>deno</category>
      <category>node</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
    <item>
      <title>Using mocked APIs to increase developer productivity</title>
      <dc:creator>Alexandre</dc:creator>
      <pubDate>Wed, 22 May 2019 15:57:49 +0000</pubDate>
      <link>https://dev.to/asantos00/using-mocked-apis-to-increase-developer-productivity-13a6</link>
      <guid>https://dev.to/asantos00/using-mocked-apis-to-increase-developer-productivity-13a6</guid>
      <description>&lt;p&gt;When we’re developing a frontend, we just might be lucky enough to have a full-fledged API, although in the real world, for the most time,  we’ll get ourselves into a position where we have to develop without an API is available with all the functionality we require in the future.&lt;/p&gt;

&lt;p&gt;There are a few tools that enable us to minimize this dependency, I remember &lt;code&gt;ember&lt;/code&gt; has the great &lt;code&gt;ember-cli-mirage&lt;/code&gt;. It provides the functionality you need, deeply integrated with &lt;code&gt;ember&lt;/code&gt; and makes you develop &lt;strong&gt;by default&lt;/strong&gt; with a completely mocked API, which I think is a great principle to start with. &lt;br&gt;
It is also great to be able to run the application without depending on external servers (imagine on a plane, on a trip without internet, or just on a computer with low memory).&lt;br&gt;
You do not want your UI developers to run 3 servers just to develop a button.&lt;/p&gt;
&lt;h2&gt;
  
  
  Usecase
&lt;/h2&gt;

&lt;p&gt;The last days we were faced with a similar issue. We're developing a screen, we had the API signature, but the API was not ready yet.&lt;/p&gt;

&lt;p&gt;One alternative would be to just have the payload somewhere hardcoded, while we were waiting for the finished API. &lt;br&gt;
Sure, we can develop your button with that but then it is not possible to implement the part of the application that does the requests. We also wanted, in future, to spend as little effort as possible to change from the mocked data to a real API.&lt;/p&gt;

&lt;p&gt;That solution did not look right, especially when we still remember &lt;code&gt;ember-cli-mirage&lt;/code&gt;. Unfortunately, we can't use &lt;code&gt;ember-cli-mirage&lt;/code&gt; with other libraries, even though we really miss the functionality it provides.&lt;/p&gt;

&lt;p&gt;The solution we ended up with was a combination of &lt;code&gt;json-server&lt;/code&gt; with &lt;code&gt;route-parser&lt;/code&gt; and using &lt;code&gt;axios&lt;/code&gt; request interceptors.&lt;/p&gt;

&lt;p&gt;In our http-client we had calls to &lt;code&gt;axios&lt;/code&gt;, so, the first thing we did was to add this line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// httpClient.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mockApiRequestInterceptor&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./mockApiRequestInterceptor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interceptors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockApiRequestInterceptor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Please keep in mind that if you use axios instance, &lt;/span&gt;
&lt;span class="c1"&gt;// you have to do it on the instance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And we've created the request interceptor&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mockApiRequestInterceptor.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;UrlPattern&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;route-parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;API_BASE_URL&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;appConfig&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MOCK_API_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3001/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MOCK_URLS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/:user/posts/:id`&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;IS_DEVELOPMENT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&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;matchedUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MOCK_URLS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockUrl&lt;/span&gt; &lt;span class="o"&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="nx"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;UrlPattern&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockUrl&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;pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matchedUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;API_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MOCK_API_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&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 mocked URLs would be added to &lt;code&gt;MOCK_URLS&lt;/code&gt;, and if there is a &lt;em&gt;mocked version of them&lt;/em&gt; they will be redirected.&lt;/p&gt;

&lt;p&gt;So, this code would redirect requests made from a URL that is &lt;code&gt;https://mycrazyserver.com/api/asantos00/posts/123&lt;/code&gt; to &lt;code&gt;http://localhost:3001/api/asantos00/posts/123&lt;/code&gt;, and part of the problem was solved.&lt;/p&gt;

&lt;p&gt;After this, we took advantage of another great package &lt;code&gt;json-server&lt;/code&gt; (TLDR: &lt;em&gt;Serves JSON files through REST routes&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;We've created an npm script that runs this &lt;code&gt;json-server&lt;/code&gt; with a few configurations (I will explain them later).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"mock-api:serve"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"json-server --watch mock-api/db.json --port 3001 --routes mock-api/routes.json"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And created a &lt;code&gt;db.json&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;mock-api/db.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"posts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mocking an API with axios"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"asantos00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1557937282&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lorem ipsum dolor sit amet, consectetur."&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Whatever post"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"asantos00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;758851200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lorem ipsum dolor sit amet, consectetur."&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It automatically creates rest endpoints for every entity on the &lt;code&gt;db.json&lt;/code&gt; file and watches the db file for changes.&lt;/p&gt;

&lt;p&gt;As we said before, &lt;code&gt;json-server&lt;/code&gt; creates REST endpoints for entities, this means that after we have the entity &lt;code&gt;post&lt;/code&gt; on the &lt;code&gt;db.json&lt;/code&gt;, the following endpoints are created:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET /posts&lt;/code&gt; - Returns the list of posts&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /posts/:id&lt;/code&gt; - Returns post with the sent id&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /posts&lt;/code&gt; - Creates a post&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PUT /posts/:id&lt;/code&gt; - Replaces the post with the sent id&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The file to create custom routes is &lt;code&gt;routes.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;mock-api/routes.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"/api/*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/$1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"/:user/posts/:id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/posts?user=:user"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The routes file only says that whatever request comes to &lt;code&gt;/:user/posts/:id&lt;/code&gt;, we redirect to the &lt;em&gt;automatically created&lt;/em&gt; endpoint that is &lt;code&gt;/posts&lt;/code&gt;. And yeah,&lt;code&gt;json-server&lt;/code&gt; also supports filtering, we use the query param &lt;code&gt;user&lt;/code&gt; to do it here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's done!&lt;/strong&gt; Now, our app will continue making the requests to the endpoints that are implemented. But we can keep developing this page with the mocked API. &lt;br&gt;
As soon as we want to use the real API, it is just a matter of removing the url from &lt;code&gt;MOCK_URLS&lt;/code&gt; (which can also be extracted to a separate file) in &lt;code&gt;mockApiRequestInterceptor&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In the end, this solution really improves the process, helping us not being concerned about backend endpoints being done or not, while implementing all the cases in a &lt;em&gt;closer to real&lt;/em&gt; environment. &lt;br&gt;
Another nice thing about this is that it is also &lt;strong&gt;library agnostic&lt;/strong&gt; as it only depends on the &lt;em&gt;http-client&lt;/em&gt; so you can use it from &lt;code&gt;react&lt;/code&gt; to &lt;code&gt;backbone.js&lt;/code&gt; or even to &lt;code&gt;react-native&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;None of this would be possible without the &lt;strong&gt;amazing open source packages&lt;/strong&gt; I've used, it was just a matter of getting the pieces together for the explained use case.&lt;/p&gt;

&lt;p&gt;What solutions do you use to solve this problem? Is it something you stumble upon frequently?&lt;/p&gt;

</description>
      <category>mockapi</category>
      <category>javascript</category>
      <category>productivity</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
