<?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: Sahu, S</title>
    <description>The latest articles on DEV Community by Sahu, S (@mrsauravsahu).</description>
    <link>https://dev.to/mrsauravsahu</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%2F438066%2Fb44a4bac-213e-4c3c-9535-07a87618bb3f.jpeg</url>
      <title>DEV Community: Sahu, S</title>
      <link>https://dev.to/mrsauravsahu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mrsauravsahu"/>
    <language>en</language>
    <item>
      <title>(Should you) Get started with vim</title>
      <dc:creator>Sahu, S</dc:creator>
      <pubDate>Thu, 30 Jun 2022 20:08:50 +0000</pubDate>
      <link>https://dev.to/mrsauravsahu/should-you-get-started-with-vim-5l8</link>
      <guid>https://dev.to/mrsauravsahu/should-you-get-started-with-vim-5l8</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;NOTE: This blog might discuss ideas which might not exactly align with you. But at the end of the day, that’s all they are, my choices. I’m always open to discussion and learning something new though.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  It’s all about editing text
&lt;/h2&gt;

&lt;p&gt;The world of text editors is very hostile from what I’ve experienced so far. You might’ve heard discussions surrounding what to use — vim, emacs, notepad, VSCode and all the other choices. I enjoyed using VSCode during my time in college. I still remember it was something new that had come out then and I enjoyed using it a lot. So why am I writing about vim now? &lt;/p&gt;

&lt;h2&gt;
  
  
  Why did I choose vim?
&lt;/h2&gt;

&lt;p&gt;It was in a CS Lab in college when I first ran into &lt;code&gt;vi&lt;/code&gt;. I was on a Fedora Machine and a &lt;code&gt;git commit&lt;/code&gt; put me into vim  (&lt;code&gt;Ctrl + C :wq&lt;/code&gt;is how you quit vim by the way). For some reason, the cryptic UI was fun to use. Ever since then, I have enjoyed it. Well, it’s improved version &lt;code&gt;vim&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On the terminal, I’m usually running something close to Ubuntu. Whether it’s inside a container, a pod running in Kubernetes, my home server (a Raspberry Pi 4 running Ubuntu Server), my personal machine on Windows running WSL. And even though Ubuntu’s default editor is nano, I find it easy to just run a &lt;code&gt;sudo apt update -y &amp;amp;&amp;amp; sudo apt install -y vim&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So should you? Use vim?
&lt;/h2&gt;

&lt;p&gt;Short answer, yeah, why not? Give it a try.&lt;/p&gt;

&lt;p&gt;Long answer. Yes, but you might not like it right away. And it’ll take a time to get used to the shortcuts. So, let’s see how to get started and take the plunge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started with vim
&lt;/h2&gt;

&lt;p&gt;When I got serious to get into vim, I didn’t realise how less &lt;strong&gt;&lt;em&gt;clear&lt;/em&gt;&lt;/strong&gt; guides were there to get started. Albeit, I was looking for how to use vim as a code editor and not a general text editor. But let’s be real, vim doesn’t really make sense as a general text editor for me. &lt;/p&gt;

&lt;h3&gt;
  
  
  The absolute absolute basics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Opening a file in vim — &lt;code&gt;vim &amp;lt;path-to-file&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Tap &lt;code&gt;i&lt;/code&gt; to insert text&lt;/li&gt;
&lt;li&gt;Now write whatever you want&lt;/li&gt;
&lt;li&gt;To exit, &lt;code&gt;Ctrl C :wq&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Plugin Manager
&lt;/h3&gt;

&lt;p&gt;So, the first thing I started to look for is a package manager, or a plugin manager as it’s in the vim world. Plugins add a lot of extra features. I ended up using &lt;a href="https://github.com/VundleVim/Vundle.vim"&gt;Vundle&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To set it up, it’s just a single command —&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  .vimrc
&lt;/h3&gt;

&lt;p&gt;Just like everything else in the shell, vim has its own rc file which we can use to customize it to our needs. Because vim is all about getting to my development environment as fast as possible, I have put my .vimrc file up on github — &lt;a href="https://github.com/cli-config/cli-config/blob/main/profiles/mrsauravsahu/.vimrc"&gt;https://github.com/cli-config/cli-config/blob/main/profiles/mrsauravsahu/.vimrc&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tabs v spaces
&lt;/h3&gt;

&lt;p&gt;I like to use spaces because it is consistent across machines &amp;amp; I use 2 spaces. That’s what the following snippet does (it should also be in .vimrc)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="s2"&gt;" use spaces instead of tabs
set tabstop=2 shiftwidth=2 expandtab
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Time for some plugins
&lt;/h3&gt;

&lt;p&gt;Because I have Vundle setup now, I can install some plugins. Here’s the entire &lt;code&gt;.vimrc&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;syntax on

&lt;span class="nb"&gt;set &lt;/span&gt;number

&lt;span class="s2"&gt;" use spaces instead of tabs
set tabstop=2 shiftwidth=2 expandtab

"&lt;/span&gt; git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim
&lt;span class="nb"&gt;set &lt;/span&gt;rtp+&lt;span class="o"&gt;=&lt;/span&gt;~/.vim/bundle/Vundle.vim
call vundle#begin&lt;span class="o"&gt;()&lt;/span&gt;
Plugin &lt;span class="s1"&gt;'bling/vim-airline'&lt;/span&gt;
Plugin &lt;span class="s1"&gt;'prabirshrestha/vim-lsp'&lt;/span&gt;
Plugin &lt;span class="s1"&gt;'mattn/vim-lsp-settings'&lt;/span&gt;
Plugin &lt;span class="s1"&gt;'prabirshrestha/asyncomplete.vim'&lt;/span&gt;
Plugin &lt;span class="s1"&gt;'prabirshrestha/asyncomplete-lsp.vim'&lt;/span&gt;
Plugin &lt;span class="s1"&gt;'junegunn/fzf'&lt;/span&gt;
Plugin &lt;span class="s1"&gt;'junegunn/fzf.vim'&lt;/span&gt;
Plugin &lt;span class="s1"&gt;'ledesmablt/vim-run'&lt;/span&gt;
Plugin &lt;span class="s1"&gt;'dense-analysis/ale'&lt;/span&gt;
Plugin &lt;span class="s1"&gt;'hashivim/vim-terraform'&lt;/span&gt;
call vundle#end&lt;span class="o"&gt;()&lt;/span&gt;

&lt;span class="s2"&gt;" show spaces
set listchars=trail:·,lead:·
set list

"&lt;/span&gt; SHORTCUTS

&lt;span class="s2"&gt;" vim-run
nnoremap &amp;lt;silent&amp;gt; &amp;lt;C-x&amp;gt; :Run

"&lt;/span&gt; formatting
nnoremap &amp;lt;silent&amp;gt; &amp;lt;C-k&amp;gt;&amp;lt;C-d&amp;gt; :gg&lt;span class="o"&gt;=&lt;/span&gt;G &amp;lt;CR&amp;gt;

&lt;span class="s2"&gt;" fzf.vim
let fzf_default_command='find -L'
nnoremap &amp;lt;silent&amp;gt; &amp;lt;C-l&amp;gt; :Files &amp;lt;CR&amp;gt;
nnoremap &amp;lt;silent&amp;gt; &amp;lt;C-p&amp;gt; :GFiles &amp;lt;CR&amp;gt;

"&lt;/span&gt; UNUSED PLUGINS &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;now
&lt;span class="s2"&gt;" Plugin 'scrooloose/nerdtree'
"&lt;/span&gt; nnoremap &amp;lt;leader&amp;gt;n :NERDTreeFocus&amp;lt;CR&amp;gt;
&lt;span class="s2"&gt;" nnoremap &amp;lt;C-n&amp;gt; :NERDTree&amp;lt;CR&amp;gt;
"&lt;/span&gt; nnoremap &amp;lt;C-e&amp;gt; :NERDTreeToggle&amp;lt;CR&amp;gt;
&lt;span class="s2"&gt;" nnoremap &amp;lt;C-f&amp;gt; :NERDTreeFind&amp;lt;CR&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Brief about Modes
&lt;/h3&gt;

&lt;p&gt;vim uses modal editing. Keys behave differently in different modes. The modes are - normal, insert, command.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Normal - Just viewing the file and basically navigating through a file&lt;/li&gt;
&lt;li&gt;Insert - You’re inserting/editing text in the file&lt;/li&gt;
&lt;li&gt;Command - Shortcuts you can execute to help your workflow (most of these are defined, and you can create your own too)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Shortcuts
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Few of these shortcuts depend on the plugins I’ve setup.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Keyboard shortcuts are something that’ll become a key reason you’ll keep using vim. I discovered few of these by accident and some by searching online. (shown in the &lt;code&gt;.vimrc&lt;/code&gt; above)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Ctrl P&lt;/code&gt; - When writing stuff (in insert mode) - this shows you suggestions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl P&lt;/code&gt; - When in normal mode - this will show you files in the current directory’s git repo - Fails if not in a git repo. This helps to not pollute the list with ignored files in git.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl L&lt;/code&gt; - When in normal mode - this shows all files in the current directory&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gg&lt;/code&gt; - Go to top of the file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Shift G&lt;/code&gt; - Go to end of file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$&lt;/code&gt; - Go to end of current line&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0&lt;/code&gt; - Go to beginning of current line&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Commands
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Few of these commands depend on the plugins I’ve setup.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s see some commands that can help your workflow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;:&amp;lt;line-number&amp;gt;&lt;/code&gt; - Go to line&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:! &amp;lt;command&amp;gt;&lt;/code&gt; - Run a command in your &lt;code&gt;$SHELL&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:sh&lt;/code&gt; - Put vim process in background and go back to your shell. &lt;code&gt;exit&lt;/code&gt; the shell to get back to &lt;code&gt;vim&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Clearly, vim has a lot of things going for it but also comes with a pretty steep learning curve. It might fit your needs or you might learn some new things in the shell. I’ve been having fun and trying to learn vim by using it on a daily basis.&lt;/p&gt;

&lt;p&gt;I’ll be updating this article as I learn about new plugins, shortcuts and commands. Make sure you bookmark it.&lt;/p&gt;

&lt;p&gt;And yeah, give vim a try.&lt;/p&gt;

&lt;p&gt;-S&lt;/p&gt;

</description>
      <category>vim</category>
      <category>linux</category>
      <category>beginners</category>
    </item>
    <item>
      <title>File Uploads on GraphQL: Why or Why not</title>
      <dc:creator>Sahu, S</dc:creator>
      <pubDate>Sat, 13 Nov 2021 18:58:27 +0000</pubDate>
      <link>https://dev.to/mrsauravsahu/file-uploads-on-graphql-why-or-why-not-ek0</link>
      <guid>https://dev.to/mrsauravsahu/file-uploads-on-graphql-why-or-why-not-ek0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Note: The code mentioned in this post can be found in these repositories. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NestJS Reference - &lt;a href="https://github.com/mrsauravsahu/blog-graphql-nestjs-fileupload"&gt;mrsauravsahu/blog-graphql-nestjs-fileupload&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;.NET Reference - &lt;a href="https://github.com/mrsauravsahu/blog-graphql-dotnet-fileupload"&gt;mrsauravsahu/blog-graphql-dotnet-fileupload&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you just want to see how to do file uploads with GraphQL, just click here&lt;/p&gt;

&lt;p&gt;GraphQL has become quite popular due to its various features fixing under/over fetching issues. It also allows for easy caching, federation, non-versioning APIs, subscriptions etc,.&lt;/p&gt;

&lt;p&gt;For the modern Internet where data needs to be accessible on various types of applications running on various types of devices, GraphQL seems like a great way forward and also a good concept to put into your knowledge bag.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are we trying to do?
&lt;/h2&gt;

&lt;p&gt;GraphQL request and responses are typically in JSON format even though the &lt;a href="http://spec.graphql.org/"&gt;GraphQL Spec&lt;/a&gt; doesn't mandate any format.&lt;/p&gt;

&lt;p&gt;All data fetching and uploading can be done easily with GraphQL and responses can also use GZIP for compression.&lt;/p&gt;

&lt;p&gt;One thing GraphQL lacks (or rather doesn't have a standard implementation for) is File Uploads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why/Why not?
&lt;/h2&gt;

&lt;p&gt;There's no right or wrong here, but here are a few things to consider when you want to have file uploads and you also have a GraphQL API.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Standardization: Because typically GraphQL APIs use JSON format, they don't require Content Negotiation. This means that File Uploads, which use a multipart format, can be tricky to standardize. Most GraphQL implementations do provide provisions to implement File Uploads through your GraphQL API however.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fully-Featured: All GraphQL APIs will use a text-based response format, so file downloads will still require a separate endpoint. This means your file upload and download will become separated. Decide based on whether you're fine with this or not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All ingress at one-point: A good reason why you might want to use File Uploads through GraphQL is because you can still make sure all incoming data into your system is through the same endpoint. Not a strong argument, but traffic management does become easier. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  File Upload Approaches for GraphQL
&lt;/h2&gt;

&lt;p&gt;Few ways to go about it - &lt;/p&gt;

&lt;h3&gt;
  
  
  1. Files as strings
&lt;/h3&gt;

&lt;p&gt;If your APIs deal with very small files, you can get away with a simple conversion from the binary representation of your file to a base64 string.&lt;/p&gt;

&lt;p&gt;Let's see a simple example. If your file has the following content.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;upload.txt
hello this is a simple file to be uploaded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use an &lt;code&gt;input&lt;/code&gt; field to get the file in the Frontend and read its contents (with a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/FileReader"&gt;FileReader&lt;/a&gt; perhaps) and then create a base64 string with the &lt;code&gt;window.btoa&lt;/code&gt; WebAPI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello this is a simple file to be uploaded&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aGVsbG8gdGhpcyBpcyBhIHNpbXBsZSBmaWxlIHRvIGJlIHVwbG9hZGVk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From now, your file can be treated as a base64 string so processing it is fairly similar to how you process regular strings in your application.&lt;/p&gt;

&lt;p&gt;Note: As file sizes grow, your application needs to be able to handle larger strings as payload and response sizes will drastically increase.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. All File Handling happens on a separate endpoint
&lt;/h3&gt;

&lt;p&gt;This would mean that your files can be uploaded to a separate REST endpoint, either hand-written or something like a pre-signed URL upload to a Storage Account on Microsoft Azure/S3 on Amazon Web Services.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt; 3. File Uploads through GraphQL
&lt;/h3&gt;

&lt;p&gt;Finally! As mentioned earlier, some GraphQL implementations do allow uploading files with a multipart/form-data request format. &lt;/p&gt;

&lt;p&gt;Let's now see how this can be done with a NestJS GraphQL Server and a .NET GraphQL Server (with HotChocolate)&lt;/p&gt;

&lt;h4&gt;
  
  
  - GraphQL Server on NestJS
&lt;/h4&gt;

&lt;p&gt;For NestJS, the GraphQL setup is fairly simple, read more about it here - &lt;a href="https://docs.nestjs.com/graphql/quick-start"&gt;docs.nestjs.com/graphql/quick-start&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This uses the Apollo GraphQL Server, which does have support for File Uploads albeit through a different package.&lt;/p&gt;

&lt;p&gt;So let's install this package. This is the &lt;code&gt;graphql-upload&lt;/code&gt; package, and because we're using TypeScript, it's good to also install the typings for it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i graphql-upload &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm i &lt;span class="nt"&gt;-D&lt;/span&gt; @types/graphql-upload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;NestJS uses TypeGraphQL behind the scenes, which means our GraphQL Schema can be generated from TypeScript classes. I have a basic Model here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ObjectType&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;@nestjs/graphql&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="nd"&gt;ObjectType&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;nullable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;coverPhotoLength&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Field&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;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;nullable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;coverPhoto&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;private&lt;/span&gt; &lt;span class="nx"&gt;_coverPhoto&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Buffer&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;This is a basic model to store details about a user, or a person rather. &lt;/p&gt;

&lt;p&gt;For our File Upload to work, we need to initialize the &lt;code&gt;graphql-upload&lt;/code&gt; package in our &lt;code&gt;main.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NestFactory&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;@nestjs/core&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;AppModule&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;./app.module&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;graphqlUploadExpress&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;graphql-upload&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;bootstrap&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;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;8080&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;app&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;NestFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Allow maximum file size of 2 Megabytes - &lt;/span&gt;
  &lt;span class="c1"&gt;// change based on your needs and &lt;/span&gt;
  &lt;span class="c1"&gt;// what your server can handle&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graphqlUploadExpress&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;maxFileSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`App running at &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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getUrl&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;bootstrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Let's add a mutation which allows the consumer of our GraphQL API to upload a file and we'll return the length of the file in bytes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Resolver&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;@nestjs/graphql&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;Person&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;./person.model&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;GraphQLUpload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FileUpload&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;graphql-upload&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;fs&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;fs/promises&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="nd"&gt;Resolver&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;PersonResolver&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Saurav&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sahu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;...&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;coverPhoto&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="nx"&gt;uploadCoverPhoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&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;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;GraphQLUpload&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="nx"&gt;FileUpload&lt;/span&gt;&lt;span class="p"&gt;,&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="kr"&gt;number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createReadStream&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;file&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;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createReadStream&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;chunks&lt;/span&gt; &lt;span class="o"&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;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&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;Buffer&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;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;let&lt;/span&gt; &lt;span class="na"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;end&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunks&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;base64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;// If you want to store the file, this is one way of doing&lt;/span&gt;
      &lt;span class="c1"&gt;// it, as you have the file in-memory as Buffer&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;upload.jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coverPhotoLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coverPhoto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;base64&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;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;err&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Here, the &lt;code&gt;GraphQLUpload&lt;/code&gt; type creates a scalar in our GraphQL Schema which allows for uploading. As you can see, we get the stream in our handler and we can do any type of processing on it.&lt;/p&gt;

&lt;p&gt;We're putting the chunks of the multipart upload together and then writing to a file, but you can also pipe the readStream to a file directly. This is just to show that you can handle the raw bytes in your file.&lt;/p&gt;

&lt;p&gt;However, this code looks a bit unwieldy due to the stream events, so thanks to a newer node feature, we can use a &lt;code&gt;for await&lt;/code&gt; loop instead.&lt;/p&gt;

&lt;p&gt;We can replace the &lt;code&gt;stream.on&lt;/code&gt; calls with this -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createReadStream&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;chunks&lt;/span&gt; &lt;span class="o"&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;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&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;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunks&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;This is pretty neat, isn't it.&lt;br&gt;
So, that's how you can implement File Uploads on your GraphQL API with NestJS.&lt;/p&gt;
&lt;h4&gt;
  
  
  GraphQL Server on .NET (HotChocolate)
&lt;/h4&gt;

&lt;p&gt;HotChocolate, one of the most popular GraphQL libraries for .NET also has an implementation for File Uploads.&lt;/p&gt;

&lt;p&gt;At the time of writing, I was on an RC version of .NET 6. But this works for .NET 6.0.100 as well. Yay! this means there's really less code.&lt;/p&gt;

&lt;p&gt;This is my Program.cs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;HotChocolate.Types&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;BlogGraphQLFileUpload.GraphQL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Add services to the container.&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddGraphQLServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddQueryType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddMutationType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Mutation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UploadType&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Configure the HTTP request pipeline.&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthorization&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapControllers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseRouting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseEndpoints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;endpoints&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGraphQL&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see I'm setting up GraphQL with Services. To allow file uploads, I have to add the Upload Scalar to my GraphQL Schema. This is done with the &lt;code&gt;builder.Services.AddType&amp;lt;UploadType&amp;gt;()&lt;/code&gt; call.&lt;/p&gt;

&lt;p&gt;Now we can write a similar mutation to handle our File Upload, which is the &lt;code&gt;Mutation&lt;/code&gt; class I have registered in this case.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;BlogGraphQLFileUpload.Data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;HotChocolate.Types&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;BlogGraphQLFileUpload.GraphQL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Mutation&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;coverPhoto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IFile&lt;/span&gt; &lt;span class="n"&gt;file&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="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OpenReadStream&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;streamWriter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FileStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"./output.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FileMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenOrCreate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CopyToAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;streamWriter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;GlobalData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CoverPhotoLength&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;GlobalData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CoverPhotoLength&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;HotChocolate gives you an &lt;code&gt;IFile&lt;/code&gt; interface to work with, and you can get the stream from there. Now you have the power to process it however it makes sense for your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt; Testing your File Uploads
&lt;/h3&gt;

&lt;p&gt;At the time of writing, Apollo Playground doesn't support File Uploads through its UI. So you're going to have to use Postman to test out your File upload&lt;/p&gt;

&lt;p&gt;Shoutout to this answer on Stack Overflow - helped a lot - &lt;a href="https://stackoverflow.com/a/61892790/5640343"&gt;https://stackoverflow.com/a/61892790/5640343&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also use the same thing with a curl command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nt"&gt;--request&lt;/span&gt; POST &lt;span class="s1"&gt;'http://localhost:8080/graphql'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'operations="{\"query\": \"mutation updateProfilePhoto($file: Upload!) {  coverPhoto(file: $file)} \", \"variables\": {\"file\": null}}"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'map="{\"0\": [\"variables.file\"]}"'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--form&lt;/span&gt; &lt;span class="s1"&gt;'0=@"./assets/grand-palais-mrsauravsahu.jpg"'&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Here, the &lt;code&gt;map&lt;/code&gt; property maps our file and passes it on to our handler. You should also be able to get the mime-type and add more logic for those. &lt;/p&gt;

&lt;p&gt;So, this was how you can do File Uploads with GraphQL, and also a few thoughts on if you really should? You can find the full code base in the links at the top.&lt;/p&gt;

&lt;p&gt;Have a great one! &lt;/p&gt;

&lt;p&gt;- Saurav, &lt;code&gt;@mrsauravsahu&lt;/code&gt; everywhere.&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>dotnet</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I automated publishing my VSCode Extension</title>
      <dc:creator>Sahu, S</dc:creator>
      <pubDate>Sun, 03 Oct 2021 10:08:43 +0000</pubDate>
      <link>https://dev.to/mrsauravsahu/i-automated-publishing-my-vscode-extension-1m71</link>
      <guid>https://dev.to/mrsauravsahu/i-automated-publishing-my-vscode-extension-1m71</guid>
      <description>&lt;p&gt;Github Actions has changed the way CI/CD is done for Open-Source projects. In this blog post, I want to show you one awesome way this has come in handy, in one of my projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Premise
&lt;/h2&gt;

&lt;p&gt;I manage &lt;a href="https://github.com/mrsauravsahu/vscode-manager"&gt;'Custom Profiles for VSCode'&lt;/a&gt;, which is an extension to help you create isolated VSCode Instances and also for teams to align on their VSCode configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Every time I make an improvement to the project, I have to do this additional task of creating a .vsix bundle and upload it to the VSCode Marketplace. What I'd love to do is, merge my code changes and automate all the deployment related tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Github Actions to the Rescue
&lt;/h2&gt;

&lt;p&gt;I chose to tackle this with Github Actions. I create a PR - which should ideally try to build and test my package and once merged, automatically deploy to the VSCode Marketplace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's Dive into the Code
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;All the code is available on github in the 'Custom Profiles for VSCode' repository. You can find the workflow file here - &lt;a href="https://github.com/mrsauravsahu/vscode-manager/blob/cool/.github/workflows/cd.yml"&gt;cd.yml&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's the simple workflow file I used to automate the deployment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cd"&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cool&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;cd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout to branch&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup node.js&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.NODE_VERSION }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install packages&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Calculate version&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;calculateVersion&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;APP_VERSION=`cat package.json | jq ".version" -M | sed 's/\"//g'`&lt;/span&gt;
          &lt;span class="s"&gt;echo "::set-output name=AppVersion::$APP_VERSION"&lt;/span&gt;
          &lt;span class="s"&gt;echo "app version = v$APP_VERSION"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build VSIX package&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run build -- -o custom-profiles-for-vscode.v${{ steps.calculateVersion.outputs.AppVersion }}.vsix&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish extension package&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;VSCODE_MARKETPLACE_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.VSCODE_MARKETPLACE_TOKEN }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run vsce -- publish -p $VSCODE_MARKETPLACE_TOKEN&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v2&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload artifact&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;custom-profiles-for-vscode.v${{ steps.calculateVersion.outputs.AppVersion }}.vsix&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;custom-profiles-for-vscode.v${{ steps.calculateVersion.outputs.AppVersion }}.vsix&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The steps should be fairly simple to understand, which include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;get the code from my branch&lt;/li&gt;
&lt;li&gt;setup node.js on the Runner&lt;/li&gt;
&lt;li&gt;install the npm packages&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  4. Calculate the version
&lt;/h3&gt;

&lt;p&gt;I'm using the version field in the &lt;code&gt;package.json&lt;/code&gt; file to determine which version of the package I need to deploy. &lt;/p&gt;

&lt;p&gt;This is not an issue even if I forget to bump the version, as the deployment would anyway fail.&lt;/p&gt;

&lt;p&gt;I will integrate GitVersion with this at some point. Stay tuned for that blog post! 😁&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Building the project
&lt;/h3&gt;

&lt;p&gt;I'm using &lt;a href="https://github.com/microsoft/vscode-vsce"&gt;VSCE - VSCode Extension Manager&lt;/a&gt; package to build and deploy my project to the Marketplace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="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="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(rm -rf out || true) &amp;amp;&amp;amp; mkdir out &amp;amp;&amp;amp; cp package.json out &amp;amp;&amp;amp; vsce package"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here I copy the package.json and the contents of the build and get ready to deploy. This creates the &lt;code&gt;.vsix&lt;/code&gt; file which we'll check out later.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Deploy to Marketplace
&lt;/h3&gt;

&lt;p&gt;Again, VSCE comes handy to push the build to the marketplace. I've added a token for authentication.&lt;/p&gt;

&lt;p&gt;You can create this token through Azure DevOps. Check this page for more details - &lt;a href="https://code.visualstudio.com/api/working-with-extensions/publishing-extension"&gt;https://code.visualstudio.com/api/working-with-extensions/publishing-extension&lt;/a&gt;. You need a token with the &lt;code&gt;marketplace:manage&lt;/code&gt; scope and you should be good to go.&lt;/p&gt;

&lt;p&gt;Inject this as a secret in your Github repository's Secrets page, and you'll be able to use it in your Workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Publishing an artifact
&lt;/h3&gt;

&lt;p&gt;If the VSCode Marketplace isn't your thing, I also publish the extension as a &lt;code&gt;.vsix&lt;/code&gt; file which can be installed in VSCode by using the Command Palette (Ctrl/Cmd + Shift + P) and then &lt;code&gt;Extensions: Install from VSIX&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And it's that easy to automate deployment for your VSCode Extension Projects to the Marketplace! Give it a try, I'm sure it'll save a you a lot of time.&lt;/p&gt;

&lt;p&gt;Have a great one. 👋&lt;/p&gt;

&lt;p&gt;-Saurav&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>github</category>
      <category>opensource</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Referential Data Validations with yupjs</title>
      <dc:creator>Sahu, S</dc:creator>
      <pubDate>Sun, 23 May 2021 14:35:12 +0000</pubDate>
      <link>https://dev.to/mrsauravsahu/referential-data-validations-with-yupjs-3ieb</link>
      <guid>https://dev.to/mrsauravsahu/referential-data-validations-with-yupjs-3ieb</guid>
      <description>&lt;h2&gt;
  
  
  What is Data Validation?
&lt;/h2&gt;

&lt;p&gt;Data validation is the process of checking whether a given value fits certain criteria based on its business requirements.&lt;/p&gt;

&lt;p&gt;For any input - a UI input field or an API input body, data validation is crucial. Any arbitrary input should never be trusted. And data validation plays a vital role in making sure these inputs are rigorously funnelled through the right pipes before they create unintended side-effects in our applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Validation in the JavaScript world
&lt;/h2&gt;

&lt;p&gt;In JavaScript projects, both the browser and node.js, that is, there are several npm packages available to do data validation. I've personally used joi and yupjs.&lt;/p&gt;

&lt;p&gt;joi was my goto choice for Data Validation for a long time. It worked really well with hapijs and has a great community around it. Trust me, I don't have anything against joi, it's just that I find yupjs to be more easier for me to work with.&lt;/p&gt;

&lt;p&gt;yupjs is also a data validation library, and gets lots of its characteristics from joi but focuses more on client side validation and can be easily extended.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example of a Data Validation
&lt;/h2&gt;

&lt;p&gt;Data validations are done on each property of an incoming "Data Transfer Object". Just a fancy way 🎓 of saying an object which is created from the raw inputs and passed along for cleaning and processing before actually getting stored or used in other places of an application.&lt;/p&gt;

&lt;p&gt;Let's take a simple signup page example. We will have two inputs and the DTO will have the shape shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SignUpDto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple data validations here are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the userName and password fields are required&lt;/li&gt;
&lt;li&gt;userName should be of a maximum length of 12&lt;/li&gt;
&lt;li&gt;password should be a minimum length of 8&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter yupjs
&lt;/h2&gt;

&lt;p&gt;To achieve this, yupjs uses a concept called as a schema for validation. I'm sure you'll find the yupjs library very similar to joi, so let's take a look. The simple validations for the userName and password can be written like shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;yup&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;yup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SignUpDto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&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;signUpSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;yup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;yup&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;please enter a username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;yup&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;please enter a password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&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;As you can see, you can define custom error message for each validation as well. Now this &lt;code&gt;signUpSchema&lt;/code&gt; can be used to actually to the data validation, which is shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SignUpDto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sample&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;signUpSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;abortEarly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="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="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;ValidationError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;please&lt;/span&gt; &lt;span class="nx"&gt;enter&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;finishTestRun&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;yup&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;runTests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;63&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;yup&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;runTests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;finishTestRun&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;yup&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;runTests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;67&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;yup&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;createValidation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;127&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sample&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;please enter a password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;ValidationError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;please&lt;/span&gt; &lt;span class="nx"&gt;enter&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;
        &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;createError&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/Users/&lt;/span&gt;&lt;span class="nx"&gt;sauravsahu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Documents&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;personal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;yuppers&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;yup&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;createValidation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;sauravsahu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Documents&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;personal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;yuppers&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;yup&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;util&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;createValidation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;107&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="nx"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="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;As we can see, we get the detailed explanation as to why the validation failed in the &lt;code&gt;inner&lt;/code&gt; property. I map over the &lt;code&gt;inner&lt;/code&gt; property and keep only the path and value fields - this is enough for my frontend app to understand what localised message to show.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;signUpSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;abortEarly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;var&lt;/span&gt; &lt;span class="nx"&gt;validationErrors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&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="na"&gt;type&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="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&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;path&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="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="nx"&gt;validationErrors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;required&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;path&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;password&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;This is great, and yupjs has support for lots of different types of validations out-of-the-box, listed here - &lt;a href="%5Bhttps://github.com/jquense/yup#api%5D(https://github.com/jquense/yup#api)"&gt;yupjs API&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is referential validation?
&lt;/h2&gt;

&lt;p&gt;Unlike some validation rules which depend on just one key of a property, more complex validations could reference other properties as well. yupjs allows us to refer to other property of our DTO with &lt;code&gt;test&lt;/code&gt; methods.&lt;/p&gt;

&lt;p&gt;For our example, let's say we want to make sure the password doesn't contain the username as a string - meaning, if username is &lt;code&gt;sample&lt;/code&gt;, password cannot be &lt;code&gt;123saMplE456&lt;/code&gt; because the word sample appears in the sample. &lt;/p&gt;

&lt;p&gt;To validate this password, we need to refer to the username field as well. We can write this with the &lt;code&gt;test&lt;/code&gt; method from yupjs. Let's modify our schema as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signUpSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;yup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;yup&lt;/span&gt;
     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;please enter a username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
   &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;yup&lt;/span&gt;
     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;please enter a password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="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="s1"&gt;contains-username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&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="o"&gt;+&lt;/span&gt;      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;userName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userNameString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userName&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;containsUserName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userNameString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;containsUserName&lt;/span&gt;
&lt;span class="o"&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;As you can see, I've added default values with the null coalescing operator as &lt;code&gt;userName&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; could be falsey.&lt;/p&gt;

&lt;p&gt;Now if we try to validate our sample user, we get this validation error, which is exactly what we wanted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;contains-username&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;path&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;password&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;For the &lt;code&gt;test&lt;/code&gt; method, the first argument is the name of the validation, for us, it is &lt;code&gt;contains-username&lt;/code&gt; and the second method is the actual test function which gets the current value and the context with which it is getting validated, and we can pick the &lt;code&gt;userName&lt;/code&gt; with this context.&lt;/p&gt;

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

&lt;p&gt;yupjs is a very versatile data validation library. It can used in both the browser and in node.js. It has great in-built validators but also supports custom validation. Referential validation is a breeze and those methods can be easily unit-tested as well.&lt;/p&gt;

&lt;p&gt;yupjs also contains casting methods to transform objects from one shape to other. I'm currently enjoying yupjs on the &lt;a href="https://github.com/daily-vocab/daily-vocab"&gt;Daily Vocab App&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Have a great one! Keep on coding.&lt;/p&gt;

&lt;p&gt;- &lt;a href="https://poly.work/mrsauravsahu"&gt;mrsauravsahu&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>datavalidation</category>
      <category>yupjs</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Documenting .env files for nodejs Projects</title>
      <dc:creator>Sahu, S</dc:creator>
      <pubDate>Fri, 14 May 2021 18:51:27 +0000</pubDate>
      <link>https://dev.to/mrsauravsahu/documenting-env-files-for-nodejs-projects-3a9j</link>
      <guid>https://dev.to/mrsauravsahu/documenting-env-files-for-nodejs-projects-3a9j</guid>
      <description>&lt;p&gt;The original post is published on my Blog at &lt;a href="https://mrsauravsahu.github.io/posts/44"&gt;mrsauravsahu&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: There's a video version available where I actually build this project and deploy it to npmjs: &lt;a href="https://youtu.be/4N1lwa6w6HA"&gt;https://youtu.be/4N1lwa6w6HA&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation of any sort looks like an overhead at the time, but pays off really well for projects that need to be maintained for a long time, when teams change, when onboarding new members, and a whole lot others.&lt;/p&gt;

&lt;p&gt;For nodejs projects, application configuration is usually read from &lt;code&gt;process.env&lt;/code&gt; which in turn, come from a place like ENVIRONMENT variables or a configuration file like &lt;code&gt;.env&lt;/code&gt;. During development, this package &lt;code&gt;dotenv&lt;/code&gt; is a great tool to set your environment variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation is Key
&lt;/h2&gt;

&lt;p&gt;For large projects with even larger teams, code-base changes constantly and so does the configuration. So documentation is key to keep anyone who uses the code-base later.&lt;/p&gt;

&lt;p&gt;A typical &lt;code&gt;.env&lt;/code&gt; file looks like this (it's a collection of key=value pairs)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# The Node environment
NODE_ENV=development

# Url to a third party service
API_SERVICE_URL=https://mrsauravsahu.tech/posts/41/file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the value could contain sensitive information, to document this, we should ideally omit the value from each key=value pair and add this template of sorts to source control, which look something like the example below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# The Node environment
NODE_ENV=

# Url to a third party service
API_SERVICE_URL=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What did I build?
&lt;/h2&gt;

&lt;p&gt;I created an npm package which generates these template &lt;code&gt;.env&lt;/code&gt; files from the real .env file, called &lt;a href="https://npmjs.com/gen-env-template"&gt;gen-env-template&lt;/a&gt;.&lt;br&gt;
This is a dev tool so you can install it as a devDependency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Use your favorite package manager to install this. (You can use npx to run directly as well)
npm i -D gen-env-template
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have the package, we can pass in the &lt;code&gt;.env&lt;/code&gt; file we're using and path to the outfile file. For example, if this is our input file -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ cat .env
# The Node environment
NODE_ENV=

# Url to a third party service
API_SERVICE_URL=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can generate our template file with this command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ ./node_modules/.bin/gen-env-template .env template.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we get the generated template file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ cat template.env
# The Node environment
NODE_ENV=

# Url to a third party service
API_SERVICE_URL=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, this &lt;code&gt;template.env&lt;/code&gt; file can be safely committed to source control as all secrets have been omitted. You can find the Github repository for this project here - &lt;a href="https://github.com/mrsauravsahu/gen-env-template"&gt;mrsauravsahu/gen-env-template on Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>documentation</category>
      <category>node</category>
      <category>dotenv</category>
    </item>
  </channel>
</rss>
