<?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: efi shtain</title>
    <description>The latest articles on DEV Community by efi shtain (@efishtain).</description>
    <link>https://dev.to/efishtain</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%2F202487%2F4c699f1f-e7f2-4dd3-b527-c54fafb4adc2.png</url>
      <title>DEV Community: efi shtain</title>
      <link>https://dev.to/efishtain</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/efishtain"/>
    <language>en</language>
    <item>
      <title>CRUD API in 3 lines using NestJS</title>
      <dc:creator>efi shtain</dc:creator>
      <pubDate>Sun, 06 Mar 2022 20:37:54 +0000</pubDate>
      <link>https://dev.to/efishtain/crud-api-in-3-lines-using-nestjs-490p</link>
      <guid>https://dev.to/efishtain/crud-api-in-3-lines-using-nestjs-490p</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yJFOalyp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A4k1eivsvVupse7fG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yJFOalyp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A4k1eivsvVupse7fG" alt="" width="880" height="628"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Photo by Kier In Sight on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If it sounds like a clickbait, looks like a clickbait and smells like a clickbait, it must be… well it’s not.&lt;/p&gt;

&lt;p&gt;Here are the 3 lines to create a webserver with a crud api for a candy store which sell chocolate&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nsysX3br--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AUWhmT7hxZP3t1K1X7FVyJQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nsysX3br--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AUWhmT7hxZP3t1K1X7FVyJQ.png" alt="" width="880" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I admit it’s not a full application, but If you look closely, I said an API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why did I write this article ?
&lt;/h3&gt;

&lt;p&gt;Working with NestJS is super nice. It has an opinionated structure (that you can like or dislike), but you have to agree, it reduces a lot of the time wasted tinkering on directories structure, setting up tests, routes, database connections and so on, everything is solved for the average use case.&lt;/p&gt;

&lt;p&gt;It even comes with a great extendable CLI to facilitate everything using generators.&lt;/p&gt;

&lt;p&gt;But even with the CLI, every time I needed some kind of boiler plate code for a crud API I had to do the same stuff. Create a module, controller and a service.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;nest g module chocolate&lt;/p&gt;

&lt;p&gt;nest g controller chocolate&lt;/p&gt;

&lt;p&gt;nest g service chocolate&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then I had to add the crud APIs which are the same for each resource. And finally, If I’m really committed, I had to have some DTOs and Entities definitions.&lt;/p&gt;

&lt;p&gt;Even before I wrote any actual logic related to my application, I had to do all of that. So the generators are amazing, but not enough.&lt;/p&gt;

&lt;p&gt;But I was wrong! there are more generators, mainly the &lt;strong&gt;resource&lt;/strong&gt; generator&lt;/p&gt;

&lt;p&gt;Using the following line of bash&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;nest g resource chocolate&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I get EVERYTHING done for me in one command!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G7zgpHp6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AwXYkLbaP9XUwZI6DLfo8Uw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G7zgpHp6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AwXYkLbaP9XUwZI6DLfo8Uw.png" alt="" width="880" height="828"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;All resources created using generators&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.nestjs.com/recipes/crud-generator"&gt;Documentation | NestJS - A progressive Node.js framework&lt;/a&gt;&lt;/p&gt;




</description>
      <category>api</category>
      <category>backend</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>Dynamic AWS S3 Notification Configuration using Terraform</title>
      <dc:creator>efi shtain</dc:creator>
      <pubDate>Tue, 08 Jun 2021 16:22:09 +0000</pubDate>
      <link>https://dev.to/efishtain/dynamic-aws-s3-notification-configuration-using-terraform-ci9</link>
      <guid>https://dev.to/efishtain/dynamic-aws-s3-notification-configuration-using-terraform-ci9</guid>
      <description>&lt;p&gt;It is the simple stuff that you expect to be, well, simple. Until they aren’t.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PmkSQqVl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ABWHk3RbzVKDTvGkY" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PmkSQqVl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ABWHk3RbzVKDTvGkY" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@jstrippa?utm_source=medium&amp;amp;utm_medium=referral"&gt;James Harrison&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So the situation is like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I have an aws &lt;strong&gt;s3 bucket&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;I have multiple &lt;strong&gt;dynamically created consumers&lt;/strong&gt; for objectCreated event from this bucket&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Each consumer subscribes to specific prefix on this bucket.&lt;/strong&gt; i.e. service 1 will listen to new files on srv1/ path only. service2 will listen to new files on srv2/ path only and so on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since one SNS cannot differentiate between s3 prefixes, I need to have multiple SNS topics — one for each service&lt;/p&gt;

&lt;p&gt;Doing it manually — it is super easy, just create another pair of sns/sqs and I’m ready to go. But manual process belongs to the dark ages of 1995, I need to do it automatically using IaaC, Terraform in this case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easy, let’s do it!
&lt;/h3&gt;

&lt;p&gt;So there I went, knowing exactly what I need to do. Create a terraform file to manage the s3 bucket, sns topics and their policies, and attach each sns topic to the bucket with correct prefix (/srv1, /srv2, etc…)&lt;/p&gt;

&lt;p&gt;Like any good programmer — I wanted to copy paste stuff just to get it going, so I googled “aws s3 sns notification terrafom” and clicked the first link (which super convinently was terraform documentations). This is the link:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_notification"&gt;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_notification&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A simple note on that page caught my eyes and broke my heart:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iNfdB03f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AxhMknuPeY_oG3v6vHjUouQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iNfdB03f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AxhMknuPeY_oG3v6vHjUouQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What does that all mean??&lt;/p&gt;

&lt;h3&gt;
  
  
  Not so easy…
&lt;/h3&gt;

&lt;p&gt;well, it means that I can attach one aws_s3_bucket_notification to the bucket. It also means, I have to know in advance all topics I’m going to have since I have to write them as part of the terraform code.&lt;/p&gt;

&lt;p&gt;But I said before, I have a dynamic list of consumers, I can’t know all of them in advance, am I stuck?&lt;/p&gt;

&lt;h3&gt;
  
  
  Creativity time
&lt;/h3&gt;

&lt;p&gt;So after thinking about it for a while, I tried playing with the aws api, fetching configuration and updating it. So if I can do it using the API and get what I want, I surely can automate it!&lt;/p&gt;

&lt;p&gt;It took few trials and errors and I wrote a python script which accepts few parameters — bucket name, sns arn, and the relevant prefix. The scripts get the current configuration from aws API, check if the subscription already exists and adds it if it doesn’t.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In case someone needs the python file, I’d be happy to share it&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now I just need to run the script as part of Terraform.&lt;/p&gt;

&lt;h4&gt;
  
  
  Terraform Null resource and local exec provisioner
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;The null_resource resource implements the standard resource lifecycle but takes no further action.&lt;/p&gt;

&lt;p&gt;The triggers argument allows specifying an arbitrary set of values that, when changed, will cause the resource to be replaced.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Basically null_resource can do anything, it has no backing resource in the cloud, it has a trigger and a provisioner which runs once the trigger changed.&lt;/p&gt;

&lt;p&gt;So I’ve added a null resource wherever I have an SNS topic, pass the bucket name, the sns arn and the prefix, and that’s it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "null" {}

resource "null_resource" "s3_object_created_subscription" {

  triggers = {
     prefix = var.prefix
  }

  provisioner "local-exec" {
     command = "python ${var.bucket_name} ${var.sns_arn} ${var.prefix}"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This little piece of code can run from many terraform state files and attach an sns to a bucket with whatever prefix and how many prefixes I need. Like any terraform resource it has state, so it will run only once, unless you change the prefix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I know that’s a hack. It might break since s3 API is eventually consistent. But it does not bother me since I don’t have a massive amount of parallel changes.&lt;/p&gt;

&lt;p&gt;The reasoning behind it, vs using multiple buckets, is the bucket limit I tackled. Amazon currently allows only 1000 buckets per account. That’s actually a lot of buckets. But once you have multiple services, let’s say 30, each one requires at least 1 bucket and you have dynamic test environments, you can easily see how you reach this limit.&lt;/p&gt;




</description>
      <category>terraform</category>
      <category>aws</category>
      <category>sns</category>
      <category>s3</category>
    </item>
    <item>
      <title>VSCode find and replace using regex super powers to remove duplicates</title>
      <dc:creator>efi shtain</dc:creator>
      <pubDate>Sat, 21 Nov 2020 11:33:06 +0000</pubDate>
      <link>https://dev.to/efishtain/vscode-find-and-replace-using-regex-super-powers-to-remove-duplicates-1lgd</link>
      <guid>https://dev.to/efishtain/vscode-find-and-replace-using-regex-super-powers-to-remove-duplicates-1lgd</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NAWx8eRh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AnTNga2ytE07YLHfl" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NAWx8eRh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AnTNga2ytE07YLHfl" alt="" width="880" height="586"&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@markusspiske?utm_source=medium&amp;amp;utm_medium=referral"&gt;Markus Spiske&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It happens sometimes, mainly in documentation or comments, that a word slips twice. Not the end of the world, but if there is an easy and quick solution, why leave the wrongs unfixed?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lets fix “a a word” to “a word” without even knowing there is a problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Well, the first problem is identifying such cases. It won’t be easy to spot a a two consecutive words repeating in a long document (did you see the a a?)&lt;/p&gt;

&lt;p&gt;Then, if it happen once, it will happen again. What about other occurrences of the problem? or similar ones? It might happen a lot using the dark magic of copy pasting stuff.&lt;/p&gt;

&lt;h4&gt;
  
  
  Some background knowledge about regex
&lt;/h4&gt;

&lt;p&gt;Regex is kind of powerful (at least in spec). If you never heard of it, there is a notion of grouping and capturing. Every time you wrap part of the expression in (), it is captured, meaning grouped and numbered in increasing order, so you can use it later in the expression (without knowing the value in advance).&lt;/p&gt;

&lt;p&gt;So defining our problem, we look for full words (at least one letter), words should be bounded (so a ab won’t count as duplicate a) and there should be at least one space between the words (otherwise it is still the same word of course)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\b(\w+)\s+\1\b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This regex does exactly what we want, \b — words with a boundary, \w+ give us a word, \s+ catches at least one space. But what is the\1? and why \w+ is wrapped in parentheses? Well this are the exact captured groups we talked about before. (\w+) — match the first occurrence of a word and we capture it, \1 match the first captured group, in our case, the exact same word!&lt;/p&gt;

&lt;h4&gt;
  
  
  VSCode usage
&lt;/h4&gt;

&lt;p&gt;Vscode has a nice feature when using the search tool, it can search using regular expressions. You can click cmd+f (on a Mac, or ctrl+f on windows) to open the search tool, and then click cmd+option+r to enable regex search.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g2O-iNKv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/830/1%2ArQf64-EZH2B4cBYKlz-2xg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g2O-iNKv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/830/1%2ArQf64-EZH2B4cBYKlz-2xg.png" alt="" width="830" height="64"&gt;&lt;/a&gt;VSCode find tool, regex search activated, duplicate regex inserted&lt;/p&gt;

&lt;p&gt;Using this, you can find duplicate consecutive words easily in any document. You can also search across all your documents at once.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n1rEDE4o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/642/1%2AoOYEkiOt3dpOyq5o4TUQ6g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n1rEDE4o--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/642/1%2AoOYEkiOt3dpOyq5o4TUQ6g.png" alt="" width="642" height="130"&gt;&lt;/a&gt;Matching all duplicate consecutive words easily&lt;/p&gt;

&lt;p&gt;Now, we just need to replace the duplicate with one instance of the word. For that, toggle the replace mode (click the right arrow) and type in $1. The $1 references the same captured group as before.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N6ONgiJV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/832/1%2AjEZb4DQNHLdOiRG6TE4E1Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N6ONgiJV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/832/1%2AjEZb4DQNHLdOiRG6TE4E1Q.png" alt="" width="832" height="128"&gt;&lt;/a&gt;VSCode find and replace expanded mode&lt;/p&gt;

&lt;p&gt;Now click replace and watch the magic happens!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4w4Xniw_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/612/1%2Avwi1KyRFEdBAlwqRqkVSeA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4w4Xniw_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/612/1%2Avwi1KyRFEdBAlwqRqkVSeA.png" alt="" width="612" height="120"&gt;&lt;/a&gt;For brevity, of course there are no duplicates.&lt;/p&gt;




</description>
      <category>vscode</category>
      <category>duplicate</category>
      <category>findandreplace</category>
      <category>regex</category>
    </item>
    <item>
      <title>Firebase Firestore unit testing with jest (and kind of typescript)</title>
      <dc:creator>efi shtain</dc:creator>
      <pubDate>Wed, 06 May 2020 11:29:01 +0000</pubDate>
      <link>https://dev.to/efishtain/firebase-firestore-unit-testing-with-jest-and-kind-of-typescript-21ak</link>
      <guid>https://dev.to/efishtain/firebase-firestore-unit-testing-with-jest-and-kind-of-typescript-21ak</guid>
      <description>&lt;h3&gt;
  
  
  It took some time but I think I got it
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eeVnTzAE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AMfR1D7dDKsguQFBU" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eeVnTzAE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2AMfR1D7dDKsguQFBU" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@flowforfrank?utm_source=medium&amp;amp;utm_medium=referral"&gt;Ferenc Almasi&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was working the other day on a firebase project. The project is written using typescript, which is nice. It is basically a set of cloud functions which interacts with a Firestore database, among other things.&lt;/p&gt;

&lt;p&gt;I wanted to write unit tests and I wanted the tests to run as fast as possible without any dependencies on a real Firestore instance — so I had to mock the Firestore calls.&lt;/p&gt;

&lt;p&gt;Fair enough, should be easy… Well….&lt;/p&gt;

&lt;p&gt;I wasted so much time trying to mock the complex structure of Firestore types, using way too many Firestore internal data structures when I decided that I must be wrong. If it is hard to mock — you are doing it wrong.&lt;/p&gt;

&lt;p&gt;Let’s say I want to mock an update call on a document.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await collection('myCollection')
            .doc('myDoc')
            .update({ updated:true});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I have to mock three functions - collection, doc and update on the firestore instance i’m using. So if I’ll try to do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import \* as admin from 'firebase-admin';

let update = jest.fn()
let doc = jest.fn(()=&amp;gt;({update})
jest.spyOn(admin.firestore(), 'collection').mockReturnValue({ doc });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The compiler does not like it, it says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Argument of type ‘{ doc: any; }’ is not assignable to parameter of type ‘CollectionReference&amp;lt;DocumentData&amp;gt;’.
 Type ‘{ doc: any; }’ is missing the following properties from type ‘CollectionReference&amp;lt;DocumentData&amp;gt;’: id, parent, path, listDocuments, and 16 more.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Problem is, I don’t really need most of the functionality of a Firestore collection object or a document object, so I don’t want to waste time mocking it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution, is pretty straightforward, don’t mock what you don’t need.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Just make the return value an unknown type, and then make it any type. It’s kind of anti typescript, but for mocking external dependencies I think I can live with that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import \* as admin from 'firebase-admin';

const update = jest.fn();
const doc = jest.fn(() =&amp;gt; ({update}));
const collection = jest.spyOn(admin.firestore(), 'collection').mockReturnValue((({ doc } as unknown) as any);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;voilà&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;I can now expect what ever I want on these mocks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expect(collection).toHaveBeenCalledWith('myCollection');

expect(doc).toHaveBeenCalledWith('myPost');

expect(update).toHaveBeenCalledWith({updated:true});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Happy mocking!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>unittest</category>
      <category>firebase</category>
      <category>firestore</category>
    </item>
    <item>
      <title>Github Actions — ship code to GCP Cloud Run</title>
      <dc:creator>efi shtain</dc:creator>
      <pubDate>Wed, 11 Mar 2020 14:35:07 +0000</pubDate>
      <link>https://dev.to/efishtain/github-actions-ship-code-to-gcp-cloud-run-1gh6</link>
      <guid>https://dev.to/efishtain/github-actions-ship-code-to-gcp-cloud-run-1gh6</guid>
      <description>&lt;h3&gt;
  
  
  Github Actions — How to ship code to GCP Cloud Run
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Erw0SdOI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A15gbfnEb8070UoN-" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Erw0SdOI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2A15gbfnEb8070UoN-" alt=""&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@finalhugh?utm_source=medium&amp;amp;utm_medium=referral"&gt;Kinsey&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Deploying code to production is both time consuming and a delicate process. Getting things wrong might take your service down and eventually might hurt your users and cost you money.&lt;/p&gt;

&lt;p&gt;The solution of course is automating as much as possible.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;FYI: the blog post assumes basic knowledge in node.js/docker, a GCP account with permissions to deploy code and to create service accounts and a github account.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is GCP Cloud run?
&lt;/h3&gt;

&lt;p&gt;In the spirit of managed services, Google Cloud provides us with a service called Cloud Run.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cloud Run is a fully managed compute platform that automatically scales your stateless containers&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What can we understand from that sentence?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cloud run is a managed service&lt;/li&gt;
&lt;li&gt;Cloud run is for running &lt;strong&gt;containers&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;It scales automagiclly&lt;/li&gt;
&lt;li&gt;It is designed for stateless services&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So basically, anyone in need for running containers can benefit from using cloud run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We want to run containers!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We can wrap our code in a container, docker for example, push it to GCP’s container registry (or another registry if we want) and use the gcloud cli tool to deploy it to cloud run or do some updates from the gcp console website.&lt;/p&gt;

&lt;p&gt;But, that’s a repetitive process, it’s human error prone, and it consumes time. A wonderful oppourtonity for automatation.&lt;/p&gt;

&lt;p&gt;There are many CI/CD tools on the market, in this post we’ll focus on the kind of newish Github Actions&lt;/p&gt;

&lt;h3&gt;
  
  
  What are Github Actions?
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Github Actions give us the capability to automate processes, so we can program what we want to do and know that it repeats itself exactly the same when we need it.&lt;/p&gt;

&lt;p&gt;An action is basically a yaml file describing a series of instructions (called steps). Each step can be another action. I’m no going to go any deeper, documentation can be found here &lt;a href="https://help.github.com/en/actions/getting-started-with-github-actions/core-concepts-for-github-actions"&gt;https://help.github.com/en/actions/getting-started-with-github-actions/core-concepts-for-github-actions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One key point is: Github provides an action’s marketplace, meaning we probably won’t have to invent the wheel unless we’re doing really bleeding edge stuff. The marketplace can be found here: &lt;a href="https://github.com/marketplace?type=actions"&gt;https://github.com/marketplace?type=actions&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Alright, What’s the plan?
&lt;/h3&gt;

&lt;p&gt;We’re going to follow the next steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new Github repo&lt;/li&gt;
&lt;li&gt;Create a super simple node.js server&lt;/li&gt;
&lt;li&gt;Create the matching Dockerfile so we can containerize the server&lt;/li&gt;
&lt;li&gt;Create Github action yaml to actually build the container and deploy it to cloud run&lt;/li&gt;
&lt;li&gt;Create a service account&lt;/li&gt;
&lt;li&gt;Give the service account powers to act&lt;/li&gt;
&lt;li&gt;Update Github secrets&lt;/li&gt;
&lt;li&gt;Commit code and watch the magic happen&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Full code can be found here: &lt;a href="https://github.com/efiShtain/github-action-cloud-run"&gt;https://github.com/efiShtain/github-action-cloud-run&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Create a new Github repo
&lt;/h4&gt;

&lt;p&gt;If you already have a repo you’re working on, skip this step. Otherwise, go to Github.com, log in to your account a create a new repo, name it what ever you like and clone it to your drive&lt;/p&gt;

&lt;h4&gt;
  
  
  Create a super simple node.js server
&lt;/h4&gt;

&lt;p&gt;Run the following commands in the repo directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Initialize an npm package
npm init -y

// create source file directory
mkdir src

// create the application server entry point file
touch src/index.js

// vi to src/index.js or edit it how over you like and add the following code to it

const http = require('http');

function requestHandler(req, res) {
    res.write('ok');
    res.end();
}

const server = http.createServer(requestHandler);
const port = process.env.PORT || 8888;
server.listen(port, () =&amp;gt; console.log(`listening on port ${port}`));
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Create the matching Dockerfile
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// create the docker file
touch Dockerfile

// Add the follwing lines to Dockerfile
FROM node:alpine
WORKDIR /usr/app/src
COPY package\*.json ./

RUN npm install --production

COPY src .

CMD ["node", "index.js"]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Create Github action yaml to actually build the container and deploy it to cloud run
&lt;/h4&gt;

&lt;p&gt;Go to:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/GoogleCloudPlatform/github-actions/blob/master/example-workflows/cloud-run/.github/workflows/cloud-run.yml"&gt;GoogleCloudPlatform/github-actions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the Google cloud platform official cloud run example for github actions. Create the exact same file in your local repo under .github/workflows/cloud-run.yml&lt;/p&gt;

&lt;p&gt;We won’t deep dive to the file structure, let’s focus only on few points:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PROJECT\_ID: ${{ secrets.RUN\_PROJECT }}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That is the project id we’re going to use in gcp. To find your project id, go to &lt;a href="https://console.cloud.google.com/"&gt;https://console.cloud.google.com/&lt;/a&gt;. Log in if you need to, and open the projects list from the top left menu. In the modal window, you’ll see the list of your projects, their names and ids.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RUN\_REGION: us-central1  
SERVICE\_NAME: helloworld-nodejs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can control the service name and which region it is going to run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;service\_account\_email: ${{ secrets.SA\_EMAIL }} service\_account\_key: ${{ secrets.GOOGLE\_APPLICATION\_CREDENTIALS}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We need to provide a service account and credentials so github can control our GCP project.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;THIS IS VERY DANGEROUS AND IMPORTANT!!! RESTRICT AS MUCH ACCESS AS POSSIBLE FROM ANY SERVICE ACCOUNT&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Go over the file if you want to see the rest of the stuff that’s going on, but it is fairly basic and does exactly what we described in the manual part.&lt;/p&gt;

&lt;h4&gt;
  
  
  Create a service account and update github secrets
&lt;/h4&gt;

&lt;p&gt;Go to your GCP project console-&amp;gt; IAM &amp;amp; Admin-&amp;gt; Service account (&lt;a href="https://console.cloud.google.com/iam-admin/serviceaccounts"&gt;https://console.cloud.google.com/iam-admin/serviceaccounts&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ejXSg_mx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/926/1%2Ap5E8S1TpkT2_324DY8sfBg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ejXSg_mx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/926/1%2Ap5E8S1TpkT2_324DY8sfBg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on Create Service Account&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iWT-Il7c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2fjSj4GOY72h2wkYX5RrnA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iWT-Il7c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2fjSj4GOY72h2wkYX5RrnA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fill in service account name, i.e. github-action, and a description&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4wA5PGM---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A_DJrmpnbjKeVJsu_H6UPyw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4wA5PGM---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A_DJrmpnbjKeVJsu_H6UPyw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click Create, and continue and done in the following two screens. You should now see your service account created successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tQyctCJl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AQVYQIIMkLemB80Z6YkGhUw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tQyctCJl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AQVYQIIMkLemB80Z6YkGhUw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you remember, we had three secrets in the cloud-run.yml file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;secrets.RUN\_PROJECET
secrets.GOOGLE\_APPLICATION\_CREDENTIALS
secrets.SA\_EMAIL
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The SA_EMAIL is: github-action@…iam.gserviceaccount.com&lt;/p&gt;

&lt;p&gt;To get the GOOGLE_APPLICATION_CREDENTIALS, click on the right menu and select create key&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gGFPhNOa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/282/1%2Aed0oMVNo2s4xcGkfXGb-wA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gGFPhNOa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/282/1%2Aed0oMVNo2s4xcGkfXGb-wA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following window will show:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9_1ILmVN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AEzSSS7A_zElBrcgNfbaomg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9_1ILmVN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AEzSSS7A_zElBrcgNfbaomg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure you leave JSON selected and click create. A JSON file will be downloaded to you computer. &lt;em&gt;Any one who has that file has the service account permissions to do what ever he wants. keep it safe, surely not as part of your repository.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The final step, it to base64 the content of the JSON file. On a mac you can use the following in terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat {PATH\_TO\_DOWNLOADED\_JSON\_FILE} | base64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Save the result, we will use it soon.&lt;/p&gt;

&lt;h4&gt;
  
  
  Make sure the service account can do what it needs to do
&lt;/h4&gt;

&lt;p&gt;Our service account is worthless right now, it has no roles and it can’t do anything. Let’s give it some powers.&lt;/p&gt;

&lt;p&gt;Go to the IAM pages, click Add and write the service account name we just created in the “new member” field — it should auto complete. Add the following roles to the service account:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AJlMTyF2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AyQF9OrrQujnOcs0gEoe05w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AJlMTyF2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AyQF9OrrQujnOcs0gEoe05w.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cloud builder — allow the service account to build and submit images&lt;/li&gt;
&lt;li&gt;Service account user — allow the service account to act as the service&lt;/li&gt;
&lt;li&gt;Cloud run admin — allow the service to deploy and start containers&lt;/li&gt;
&lt;li&gt;Viewer &lt;strong&gt;on the project&lt;/strong&gt; — allow the service account to list storage objects and use them (this is where our container data is stored)&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Update Github secrets
&lt;/h4&gt;

&lt;p&gt;Alright, we’re done with GCP, Open your repo in Github’s website. Go to settings and select the secret tab&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YYtOwIUL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2idnNKnj1DzJKL-BIoEVrQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YYtOwIUL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A2idnNKnj1DzJKL-BIoEVrQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add 3 secrets to the repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RUN\_PROJECT - project id
GOOGLE\_APPLICATION\_CREDENTIALS - service account credentials, in base64 format
SA\_EMAIL - the service account email
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Commit code and watch the magic happen
&lt;/h4&gt;

&lt;p&gt;That’s it! we’re fully set! you can commit your code and let github do the work. Go to the actions page, there you would see what is going on. Here is an example from some of my playground using github actions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sref78a_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AA13Iw7EonDN9vvVynd9mzQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sref78a_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AA13Iw7EonDN9vvVynd9mzQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;This was kind of a long process, But you only have to do it once, and i tried to describe the hard parts in details.&lt;/p&gt;

&lt;p&gt;You now have a fully functioning Github Action which deploys a cloud run container and hides all the delicate repetitive tasks so you can focus on coding.&lt;/p&gt;

&lt;p&gt;With that said, this is only touching the ice tip. This solution is not fully production ready as there are more things to consider like handling failures, rollbacks, canary testing, unit testing and so on.&lt;/p&gt;

&lt;p&gt;Let me know if I have made any mistakes or if you can think of a better/easier way of doing the same&lt;/p&gt;




</description>
      <category>containers</category>
      <category>githubactions</category>
      <category>googlecloudrun</category>
      <category>cicdpipeline</category>
    </item>
    <item>
      <title>How JSON.stringify killed my express server</title>
      <dc:creator>efi shtain</dc:creator>
      <pubDate>Mon, 30 Sep 2019 20:09:12 +0000</pubDate>
      <link>https://dev.to/efishtain/how-json-stringify-killed-my-express-server-3lke</link>
      <guid>https://dev.to/efishtain/how-json-stringify-killed-my-express-server-3lke</guid>
      <description>&lt;h4&gt;
  
  
  &lt;em&gt;Getting up to 300% more performance from an express server with a simple change&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uCkw7BqG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ABQNf86bnLABOiPl7" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uCkw7BqG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/0%2ABQNf86bnLABOiPl7" alt="" width="880" height="660"&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@maxchen2k?utm_source=medium&amp;amp;utm_medium=referral"&gt;Max Chen&lt;/a&gt; on &lt;a href="https://unsplash.com?utm_source=medium&amp;amp;utm_medium=referral"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Express is one of the most used node.js frameworks out there when you need to create server.&lt;/p&gt;

&lt;p&gt;Here is an example of a simple express server with only one endpoint returning a small static JSON response.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Running the code above and benchmarking it using &lt;a href="https://www.npmjs.com/package/autocannon"&gt;autocannon&lt;/a&gt; for multiple times shows the server, running on a 2018 MacBook pro, handles roughly 190K requests in 11 seconds ~= 1900 RPS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ autocannon [http://localhost:3000/not\_cached](http://localhost:3000/not_cached)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  We can do better!
&lt;/h3&gt;

&lt;p&gt;Since there is so little code in this example, there is only one place where we can look for better performance — express source code, the definition of the json function on the response object (full code found at: &lt;a href="https://github.com/expressjs/express/blob/master/lib/response.js"&gt;https://github.com/expressjs/express/blob/master/lib/response.js&lt;/a&gt;)&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;The most important part happens in line 22, stringily —  &lt;strong&gt;for every res.json that we use, the returned value is stringifed&lt;/strong&gt; to be sent as an http response. After stringifing the data, the content type is set and response is sent.&lt;/p&gt;

&lt;p&gt;JSON.stringify is a cpu bound operation, not node’s best friend, so let’s try and do it only once.&lt;/p&gt;

&lt;p&gt;We can stringify the result and save it to variable, and for each incoming request we can set the content-type to application/json and use the end method to write the string directly to the socket:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Running autocannon again gives us around 350K requests in 11 seconds ~= 3500 RPS. 80% improvement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But wait you say, you promised me 300% improvement !! and you would be right!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The performance difference depends heavily on the object returned. I wanted to show that even a small change on a small object can be significant.&lt;/p&gt;

&lt;p&gt;Try doing the same thing with a big json object (like 500–600 Kb), you’ll get your performance boost. Actually, using res.json, might actually causes your server to crash in a limited environment like a container running on kubernetes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusions&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When using express, if your server performs poorly RPS wise, try cache any shared response and write the string directly to the response stream instead of using res.json which uses JSON.stringify everytime.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>express</category>
      <category>node</category>
    </item>
  </channel>
</rss>
