<?xml version="1.0" encoding="utf-8"?>
    <feed xmlns="http://www.w3.org/2005/Atom">
     <title>BigBinary Blog</title>
     <link href="https://www.bigbinary.com/feed.xml" rel="self"/>
     <link href="https://www.bigbinary.com/"/>
     <updated>2026-05-19T04:30:05+00:00</updated>
     <id>https://www.bigbinary.com/</id>
     <entry>
       <title><![CDATA[DNS basics and how DNS works in Neeto]]></title>
       <author><name>S Varun</name></author>
      <link href="https://www.bigbinary.com/blog/dns-basics-and-how-dns-works-in-neeto"/>
      <updated>2026-01-06T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/dns-basics-and-how-dns-works-in-neeto</id>
      <content type="html"><![CDATA[<p>This blog started with an explanation of how DNS works in<a href="https://neeto.com">Neeto</a>. However we covered a lot of ground about how DNSactually works.</p><h1>The Basics of DNS Records</h1><p>A Domain Name System (DNS) is a hierarchical and decentralized naming system forcomputers and servers connected to the Internet. It essentially translateshuman-readable domain names into machine-readable IP addresses.</p><h2>What is a Domain Name?</h2><p>A Domain Name is a unique, human-friendly label used to identify one or more IPaddresses. It's what people type into a web browser to visit a website. Forexample, <code>google.com</code> and <code>wikipedia.org</code> are domain names.</p><h2>Purchasing a New Domain Name</h2><p>You don't buy a domain name outright. Technicall,y you register the right to useit for a specified period (typically 1 to 10 years) from a Domain NameRegistrar. These are called &quot;registrars&quot; because you are registering the rightto use the domain name.</p><p>Popular Domain Name Registrars are GoDaddy, Namecheap, Cloudflare and Porkbun.</p><h2>DNS Records: Types and Uses</h2><p>DNS Records provide information about a domain, primarily mapping hostnames toIP addresses. There are many different types of DNS records. We would be lookingat the important ones.</p><h3>A Record</h3><p>&quot;A record&quot; stands for &quot;Address record&quot;. It maps a domain name (like google.com)to an IPv4 address (like 93.184.216.34).</p><h3>AAAA Record</h3><p>This does exactly the same thing as A record but for the IPv6 address. Four Assignifies a bigger address range.</p><h3>CNAME Record</h3><p>&quot;CNAME record&quot; stands for &quot;Canonical Name Record&quot;.</p><p>Instead of pointing directly to an IP address like an A record does, a CNAMEpoints one hostname to another hostname.</p><p>An example of CNAME record could be: <code>blog.bigbinary.com</code> -&gt;<code>bigbinary.github.io</code>.</p><p>What CNAME is saying here is that if you are visiting <code>blog.bigbinary.com</code>, thenthis record doesn't have the IP address information. If you want an IP address,then ask for that info from <code>bigbinary.github.io</code>. Remember that IP addressesare provided by A and AAAA records.</p><p>Another way of looking at it is that an A record provides the IP address,while CNAME provides the address of the next machine to which we can ask for theIP address.</p><p>Please note that it is quite possible that the next machine might have anotherCNAME and that in turn might have another CNAME.</p><p>The main point is that CNAME keeps the record of the next machine to ask for. Inthe end, some machine has to have an A or AAAA record so that a domain is mappedto an IP address.</p><h3>MX Record</h3><p>&quot;MX Record&quot; stands for &quot;Mail Exchanger Record&quot;.</p><p>It specifies the mail servers responsible for accepting email messages on behalfof of a domain.</p><h3>TXT Record</h3><p>A TXT record (Text record) lets a domain owner store arbitrary text data in DNS.Other services then look up that text to verify ownership, check email policies,etc. Think of it like a sticky note that the domain owner can add for others toread.</p><p>Here are some use cases of the TXT record:</p><h4>Adding SPF records</h4><pre><code class="language-sh">bigbinary.com. IN TXT &quot;v=spf1 ip4:198.51.100.10 include:_spf.google.com -all&quot;</code></pre><h4>Domain verification</h4><p>Here is an example of site verification by Google Site.</p><pre><code class="language-sh">bigbinary.com. IN TXT &quot;google-site-verification=asduiashd9812h98asdh&quot;</code></pre><h4>Adding DMARC records</h4><pre><code class="language-sh">_dmarc.bigbinary.com. IN TXT &quot;v=DMARC1; p=reject; rua=mailto:dmarc@example.com&quot;</code></pre><h3>NS Record</h3><p>NS stands for &quot;Name servers&quot;.</p><p>Let's say that a user types in the URL <code>https://blog.neeto.com</code>. The job of theDNS system is to ultimately find an IP address to which the request can be sent.Now, let's think about how to go about searching for the IP address.</p><p>We need to ask some machine for more information about <code>blog.neeto.com</code>. Thatinformation could be a CNAME record, an A record, or a AAAA record. But theproblem is who should be asked. From where we start the journey.</p><p>That's where the NS record comes into the picture. Remember, each domain isregistered with a registrar. So that's where the DNS system starts the journey.First, DNS will ask the registrar of the domain, &quot;Hey, can you give me the Nameservers to whom I can start asking questions?&quot;</p><p>Let's take a practical case and execute the following command on the terminal:</p><pre><code class="language-sh">whois neeto.com</code></pre><p>We'll get a lot of data, but we want to concentrate on the following six lines:</p><pre><code class="language-sh">Domain Name: NEETO.COMRegistrar WHOIS Server: whois.cloudflare.comRegistrar: Cloudflare, Inc.Registrar URL: https://www.cloudflare.comName Server: BARBARA.NS.CLOUDFLARE.COMName Server: YEW.NS.CLOUDFLARE.COM</code></pre><p>We can see that the Registrar for neeto.com is &quot;Cloudflare&quot;. We also see thatthe Name servers are two servers, which are also <code>clouflare.com</code>. The people whodesigned name servers dictated that there should always be at least two nameservers. In this way, if one of them goes down for any reason, the overallsystem is still working.</p><p>Taking our example of <code>blog.neeto.com</code>, if we need a CNAME record, an A record,or a AAAA record, then we need to start asking those questions to these two nameservers.</p><p>Now let's do the same experiment with another domain. This time, we will choose<code>https://bigbinary.com</code>.</p><pre><code class="language-sh">whois bigbinary.com</code></pre><p>This time, we will get the following lines.</p><pre><code class="language-sh">Domain Name: BIGBINARY.COMRegistrar: GoDaddy.com, LLCRegistrar WHOIS Server: whois.godaddy.comRegistrar URL: http://www.godaddy.comName Server: BARBARA.NS.CLOUDFLARE.COMName Server: YEW.NS.CLOUDFLARE.COM</code></pre><p>Notice that this time the registrar is <code>GoDaddy</code>, but the Name servers are<code>cloudflare.com</code>. This is because <code>bigbinary.com</code> is registered with <code>GoDaddy</code>.When a domain is purchased from a registrar, the default values of the nameservers will point to the registrar's name servers. So after the initialregistration, <code>bigbinary.com</code> had the GoDaddy name servers, but has chosen notto use them. With the help of NS records, BigBinary has told GoDaddy thatBigBinary doesn't want to use GoDaddy's name servers and wants GoDaddy to usethe Cloudflare name servers. This will mean that all the future DNS records for<code>bigbinary.com</code> can be maintained in Cloudflare.</p><p>This goes on to show that one is not restricted to the name servers of theregistrars.</p><p>Name servers, just like CNAME records, never point to an IP address. They alwayspoint to another host name.</p><h2>Different parts of a URL</h2><p><img src="/blog_images/2026/dns-basics-and-how-dns-works-in-neeto/different-parts-of-domain2.png" alt="Different parts of a URL"></p><h3>Protocol</h3><p>The protocol is the initial part that specifies the set of methods used fortransferring data between a web browser and a server. The server essentiallytells the browser how to communicate. The most common protocols are <code>http</code>(Hypertext Transfer Protocol) and its secure version <code>https</code> (Hypertext TransferProtocol Secure).</p><h4>Top-Level Domain (TLD)</h4><p>A Top-Level Domain (TLD) is the very last part of a domain name, located afterthe final dot.</p><p>For example, in google.com the <code>.com</code> is the Top-Level Domain (TLD). Common TLDsare <code>.com</code>, <code>.org</code>, <code>.net</code> etc.</p><h3>Subdomain</h3><p>A subdomain is a label that comes before the main part of a domain name.</p><p>For example, in the address blog.bigbinary.com the <code>blog</code> is the subdomain.</p><p>We can have <code>a.b.c.d.e.f.blog.bigbinary.com</code>. Technically upto 127 levels ofsubdomain is allowed.</p><h4>Root domain</h4><p>A root-level domain is the base name of a website. For example, in<code>www.google.com</code> the <code>.com</code> part is the TLD and <code>google.com</code> part is the rootlevel domain.</p><h3>Strange case of www subdomain</h3><p>Let's say that we registered a brand new domain called <code>spinjudo.com</code> withCloudflare. We have our marketing site up and running on Vercel, and we want tohost our blog on WordPress. So we will add these two DNS records.</p><p>For our marketing site, we will add a CNAME record something like this:</p><pre><code class="language-sh">spinjudo.com IN CNAME 76.76.21.21</code></pre><p>And then for the blog, we will add another CNAME record something like this:</p><pre><code class="language-sh">blog   IN   CNAME   domains.wordpress.com.</code></pre><p>So now both <code>https://spinjudo.com</code> and <code>https://blog.spinjudo.com</code> are working.</p><p>But what about <code>https://www.spinjudo.com</code>.</p><p>Developers often forget that users can type <code>https://spinjudo.com</code> or they canalso type <code>https://www.spinjudo.com</code>.</p><p>Time to time in your life, you might have come across cases where a site isworking only with <code>www</code> or only without <code>www</code>. That's because the developerseither took care of <code>www</code> and forgot to take care of the root domain or thedeveloper took care only of the root domain and not of <code>www</code>.</p><p>Technically, <code>www</code> is a subdomain and that needs to be taken care of too. Inthis case for <code>spinjudo.com</code> we need to add one more CNAME record for <code>www</code> andthat might look like this:</p><pre><code class="language-sh">www IN CNAME 76.76.21.21</code></pre><h2>Rules regarding CNAME records</h2><p>The first rule is that CNAME records can <strong>only</strong> be added to subdomains. Itmeans CNAMES can't be added to root domains. That's the rule.</p><p>However, some DNS providers allow a technique to bypass this rule. They providea different type of record called &quot;ANAME&quot; record which allows CNAME for rootdomains.</p><p>In general, we advise against using ANAME records.</p><p>The second rule is that if a subdomain has a CNAME record, then that subdomaincan't have any more records.</p><h2>Why do we need to wait for some time after updating the domain</h2><p>If you change anything related to DNS you are asked to wait 24 to 48 hours forthe change to propoage. What does that mean?</p><p>If you type www.neeto.com into your browser, it uses its DNS cache. The browsermight not even ask anyone what the ip address of www.neeto.com is. This isbecause maybe 20 seconds ago you visited www.neeto.com and now you refreshed thepage.</p><p>If the browser really needs an updated DNS value, then the browser will sendthat request to your laptop. Your laptop has a DNS cache. Your laptop might notask anyone for the updated DNS value for a while.</p><p>Now, if the laptop needs to know the DNS valu,e then the laptop will ask for anansewr to the root servers.</p><p>There are only 13 root servers in the world. These root servers are named from&quot;A&quot; to &quot;M&quot;. However just because there are 13 root servers it doesn't mean thatthere are only 13 servers. Each of those 13 root servers are running behind lotsof physical servers.</p><p>The complete list of physical servers can be found at https://root-servers.org.</p><p>Root servers do not know the answer to every question. However, they do know theaddress of the servers that can answer your questions. For example, if your TLDis <code>.com</code>, then the root server will send you to a different server. If your TLDis <code>.net</code> then you will asked to go to a different machine. Similarly, there areservers to serve TLDs like <code>.co.uk</code>, <code>.in</code> etc.</p><p><img src="/blog_images/2026/dns-basics-and-how-dns-works-in-neeto/domain-hierarchy.png" alt="Domain hierarchy"></p><p>Note that at each layer, there is some amount of DNS caching. To ensure that theupdated value is completely updated throughout the Internet of the whole worldwe need to give some time for the old cached value to be removed.</p><p>The way these servers work also shows the decentralized nature of DNS. There isno one single place where all the DNS values of the world is stored. DNS valuesare stored at different places, but there is a path to get to those values allthe way from the root servers.</p><h2>neeto-custom-domains-frontend package</h2><p>Adding a custom domain could be intimidating. People are asked to change DNSrecords, which they might not have touched for years. A small misconfigurationhas the potential to bring the whole website down. To ensure that the userexperience of adding a &quot;custom domain&quot; is great, we at<a href="https://neeto.com">Neeto</a> decided to go the extra mile.</p><p>We bought one domain each at the following name registrars:</p><ul><li>Cloudflare</li><li>Namecheap</li><li>Hostinger</li><li>Digital Ocean</li><li>Wix</li><li>Porkbun</li><li>Squarespace</li><li>AWS route 53</li><li>Network solutions</li><li>Godaddy</li><li>Strato</li><li>Microsoft 365</li></ul><p>We checked out how they ask their users to make DNS entries and we captured thescreenshots. Now, depending on what &quot;name server&quot; the user is dealing with wedisplay a help message and help screens customized for that user.</p><p>For example, if a user is using Cloudflare as their name server then the helpscreen might look like this.</p><p><img src="/blog_images/2026/dns-basics-and-how-dns-works-in-neeto/custom-domain-neeto-help-for-cloudflare.png" alt="Adding custom domain for cloudflare"></p><p>Notice that the above image has a column called &quot;Proxy&quot; which is cloudflarespecific.</p><p>If the domain registrar is GoDaddy then the help screen might look like this.</p><p><img src="/blog_images/2026/dns-basics-and-how-dns-works-in-neeto/dns-in-neeto-godaddy.png" alt="Adding custom domain for GoDaddy"></p><p>At <a href="https://neeto.com">Neeto</a> we build a number of products and almost all theproducts need the feature of &quot;custom domain&quot;. To share the code related todomain handling in a consistent manner, we have built a utility tool named<code>neeto-custom-domains-engine</code>.</p><p>When a user adds a domain to the Neeto product, this tool finds the name serverof that domain. Then we check if we have the custom help screen and helpinstructions for that name server or not. If we don't, then we provide generichelp instructions.</p><h2>Validating DNS records</h2><p>Now that the user has added the custom domain, Neeto needs to verify that thoseDNS records are indeed added.</p><p>If a user tries to add the domain <code>www.spinjudo.com</code>, then Neeto will ask theuser to add following CNAME for <code>www</code>.</p><table><thead><tr><th>Name</th><th>value</th></tr></thead><tbody><tr><td>www</td><td>dns.neetodeployapp.com</td></tr></tbody></table><p>Now, let's assume that the user has added that record. Now we need to verifythis record. Let's execute the following command from the terminal.</p><pre><code class="language-sh">nslookup -type=CNAME www.spinjudo.com</code></pre><p>We should see a response similar to this:</p><pre><code class="language-sh">Non-authoritative answer:www.spinjudo.comcanonical name = dns.neetodeployapp.com.</code></pre><p>Here We can see that the DNS record has propagated properly for this domain andit's receiving the expected value. Now, let's see how this would look for arecord without the proper records added.</p><pre><code class="language-sh">nslookup -type=CNAME www.spinjudo2.com</code></pre><p>This is the response we will get for <code>spinjudo2</code>.</p><pre><code class="language-sh">Non-authoritative answer:*** Can't find www.spinjudo2.com: No answer</code></pre><p>This could mean two things.</p><ol><li>Either the user has not added the records properly.</li><li>The records have been added, but they have not propagated properly. Sometimesit can take upto 48 hours for the added records to be seen.</li></ol><p>In this case we saw the example of validating CNAME records. However sameprocess is followed when it comes to validating A records or AAAA records.</p><h2>Traefik to route the custom domain</h2><p>Typically, when it comes to deploying an application one can deploy theapplication using services like Heroku, Render, Railways or directly on cloudservices like EC2, GCP, Azure etc. At Neeto, we decided to build NeetoDeploy.It's a service similar to Heroku for our internal use.</p><p>NeetoDeploy uses <a href="https://traefik.io/traefik">Traefik</a>, which is a leadingmodern open source reverse proxy. In simple terms, Traefik is a load balancer.All requests come to the load balancer and then the requests are routed to theright place.</p><p>Earlier, we talked about setting up a custom domain. I have setup custom domainfor <code>https://calendar.spinjudo.com</code>. As part of setting up a custom domain, Iadded a CNAME for <code>dns.neetodeployapp.com</code>.</p><p>After adding the CNAM,E Neeto validated the record. Once Neeto determines thatthe user has correctly added the CNAME then Neeto adds these custom domains toTraefik. In reality, four records are added as shown in the picture.</p><p><img src="/blog_images/2026/dns-basics-and-how-dns-works-in-neeto/spinjudo-traefik.png" alt="Adding domains to traefik"></p><p>In total, we see four records. The first records are &quot;websecure&quot;. It means theyhave <code>https</code> turned on. The last two are just <code>web</code>. It means they support<code>http</code>.</p><p>Once a request for a domain for <code>calendar.spinjudo.com</code> comes, then thoserequests will be sent to NeetoDeploy's Traefik. Traefik will map that<code>calendar.spinjudo.com</code> to an instance of the NeetoCal application and therequest will be forwarded to that server.</p><p>Please note that Traefik doesn't fulfill the request. Traefik acts as a loadbalancer and sends the request to the right server.</p><p><img src="/blog_images/2026/dns-basics-and-how-dns-works-in-neeto/traefik-handling-requests.png" alt="Traefik handling requests"></p><h2>Finding the ip address</h2><p>When a user types https://calendar.spinjudo.com, then the browser needs to knowthe ip address to which to hit. In other words, we ultimately need to know the Arecord.</p><p>We can use the tool <code>dig</code> to find the final A record value when a user visitshttps://calendar.spinjudo.com. First, let's see the tool in action.</p><pre><code class="language-sh">dig +noall +answer calendar.spinjudo.com A</code></pre><p>The response we get is following:</p><pre><code class="language-sh">calendar.spinjudo.com. 60 INCNAMEdns.neetodeployapp.com.dns.neetodeployapp.com.60INCNAMEa7b4fc193275e43ea9ba2b7753b080dc-6ad6aaca90bd0ea4.elb.us-east-1.amazonaws.com.a7b4fc193275e43ea9ba2b7753b080dc-6ad6aaca90bd0ea4.elb.us-east-1.amazonaws.com. 60 IN A 34.233.85.113</code></pre><p>The first line is a CNAME to <code>dns.neetodeployapp.com</code>.</p><p>The second line is a CNAME to an EC2 instance on AWS.</p><p>The third line is an A record, which gives us the ip address of the machine.</p><p>In the above command, we used <code>+noall</code> and <code>+answer</code>. The <code>+noall</code> is reallyuseful. It means &quot;just hide all the output&quot;. By default, <code>dig</code> output spits alot of information. By using <code>+noall</code> we tell <code>dig</code> to go on quite mode.</p><p>And then we tell <code>dig</code> to show data for the &quot;answer&quot; section by using <code>+answer</code>.</p><p>Similarly, using <code>dig +noall +authority</code> will show only the data about the&quot;authority&quot; section.</p><h2>Issuing SSL certificate</h2><p>We know that a user can visit http://spinjudo.com or the user can also visithttps://spinjudo.com. To serve HTTPS, we need SSL certificates.</p><p>We can use the user to purchase SSL certificate, configure it and apply it butthat would be too cumbersome for our users.</p><p>To generate SSL certificate we will use<a href="https://letsencrypt.org/">Let's Encrypt</a> which issues free trusted SSLcertificates.</p><p>SSL certificates are issued using the Automatic Certificate ManagementEnvironment (ACME) protocol by Let's Encrypt. This is a simple protocol by whichthe service can verify the authenticity and ownership of the requested website.</p><p>The process of domain validation, issuinga certificate and then renewingcertificate could be a bit daunting. To make life easier, Let's Encrypt hasprovided <a href="https://certbot.eff.org/">certbot</a>. This tool makes it easier to getSSL certificate from Let's Encrypt.</p><p>It's worth noting that the certificate issued by Let's Encrypt is valid only for3 months. Before the certificate expires, we need to ask Let's Encrypt to issuea new certificate and that certificate will be valid for another 90 days.</p><h2>NeetoCal using Cloudflare</h2><p><a href="https://neeto.com/cal">NeetoCal</a> and other Neeto products use Cloudflare astheir name servers.</p><p>If we look at the NeetoCal DNS record, then this is what we see.</p><p><img src="/blog_images/2026/dns-basics-and-how-dns-works-in-neeto/neetocal-dns-record.png" alt="NeetoCal DNS record"></p><p>Adding a <code>*</code> in place of the name of the record is known as a wildcardcharacter. This serves as a catch-all for any undefined subdomain, meaning allthe subdomains that do not have an explicit DNS record associated with it willbe matched by this record. As we can see in the picture above, the <code>*</code> value isproxied. What it means is that any attempt to connect to the NeetoCal IP addressfirst hits the Cloudflare server. Cloudflare server runs a bunch of checks onthe incoming requests, and then passes that request to the intended IP address.</p><p>For example, if I'm getting a lot of spammy requests from Spain, then I canconfigure Cloudflare to prevent requests coming from Spain. Or I can rate limitrequests for <code>/login</code> url and things like that.</p><p>If we do not use proxy, then that means the user is directly connecting to theNeeto server and Cloudflare is not in the picture. In this case, if a<a href="https://www.cloudflare.com/en-gb/learning/ddos/what-is-a-ddos-attack/">DDoS</a>attack happens, then Cloudflare will not be able to protect us.</p>]]></content>
    </entry><entry>
       <title><![CDATA[Automating Case Conversion in Axios for Seamless Frontend-Backend Integration]]></title>
       <author><name>Ajmal Noushad</name></author>
      <link href="https://www.bigbinary.com/blog/axios-case-conversion"/>
      <updated>2024-03-12T12:00:00+00:00</updated>
      <id>https://www.bigbinary.com/blog/axios-case-conversion</id>
      <content type="html"><![CDATA[<p>In the world of web development, conventions often differ between backend andfrontend technologies. This becomes evident when comparing variable naming caseconventions used in Ruby on Rails (snake case) and JavaScript (camel case). AtNeeto, this difference posed a major hurdle: the requirement for manual caseconversion between requests and responses. As a result, there was a significantamount of repetitive code needed to handle this conversion.</p><p>Heres a snippet illustrating the issue faced by our team:</p><pre><code class="language-js">// For requests, we had to manually convert camelCase values to snake_case.const createUser = ({ userName, fullName, dateOfBirth }) =&gt;  axios.post(&quot;/api/v1/users&quot;, {    user_name: userName,    full_name: fullName,    date_of_birth: dateOfBirth,  });// For responses, we had to manually convert snake_case values to camelCaseconst {  user_name: userName,  full_name: fullName,  date_of_birth: dateOfBirth,} = await axios.get(&quot;/api/v1/users/user-id-1&quot;);</code></pre><p>This manual conversion process consumed valuable development time and introducedthe risk of errors or inconsistencies in data handling.</p><p>To streamline our workflow and enhance interoperability between the frontend andbackend, we decided to automate case conversion.</p><h2>Implementing automatic case conversion</h2><p>Implementing automatic case conversion across Neeto products required athoughtful approach to minimize disruptions and ensure a smooth transition.Here's how we achieved this goal while minimizing potential disruptions:</p><h3>1. Axios Interceptors for Recursive Case Conversion</h3><p>We created a pair of Axios interceptors to handle case conversion for requestsand responses. The interceptors were designed to recursively convert the cases,managing the translation between snake case and camel case as data traveledbetween the frontend and backend. This smooth transition simplified theworkflow, cutting out the requirement for manual case conversion in mostsituations.</p><h3>2. Custom Parameters to Control Case Conversion</h3><p>To do a smooth rollout without breaking any products, and due to certain specialAPIs requiring specific case conventions due to legacy reasons or externaldependencies, we introduced custom parameters <code>transformResponseCase</code> and<code>transformRequestCase</code> within Axios. These parameters allowed developers toopt-out of the automatic case conversion for specific API endpoints. Byconfiguring these parameters appropriately, we prevented unintentional caseconversions where needed, maintaining compatibility with APIs that requireddifferent conventions.</p><p>This is how we crafted our axios interceptors:</p><pre><code class="language-js">import {  keysToCamelCase,  serializeKeysToSnakeCase,} from &quot;@bigbinary/neeto-cist&quot;;// To transform response data to camel caseconst transformResponseKeysToCamelCase = response =&gt; {  const { transformResponseCase = true } = response.config;  if (response.data &amp;&amp; transformResponseCase) {    response.data = keysToCamelCase(response.data);  }  return response;};// To transform error response data to camel caseconst transformErrorKeysToCamelCase = error =&gt; {  const { transformResponseCase = true } = error.config ?? {};  if (error.response?.data &amp;&amp; transformResponseCase) {    error.response.data = keysToCamelCase(error.response.data);  }  return error;};// To transform the request payload to snake_caseconst transformDataToSnakeCase = request =&gt; {  const { transformRequestCase = true } = request;  if (!transformRequestCase) return request;  request.data = serializeKeysToSnakeCase(request.data);  request.params = serializeKeysToSnakeCase(request.params);  return request;};// Adding interceptorsaxios.interceptors.request.use(transformDataToSnakeCase);axios.interceptors.response.use(  transformResponseKeysToCamelCase,  transformErrorKeysToCamelCase);</code></pre><p>Note that <code>keysToCamelCase</code>, <code>serializeKeysToSnakeCase</code> are methods from ouropen source pure utils library<a href="https://github.com/bigbinary/neeto-cist"><code>@bigbinary/neeto-cist</code></a>.</p><p>While rolling out the change to all products, we wrote a JSCodeShift script toautomatically add these flags to every Axios API requests in all Neeto productsto ensure that nothing was broken due to it. Then the team had manually wentthrough the code base and removed those flags while making the necessary changesto the code.</p><p>After the change was introduced the API code was much cleaner without theboilerplate for case conversion.</p><pre><code class="language-js">// Requestconst createUser = ({ userName, fullName, dateOfBirth }) =&gt;  axios.post(&quot;/api/v1/users&quot;, { userName, fullName dateOfBirth })// Responseconst { userName, fullName, dateOfBirth } = await axios.get(&quot;/api/v1/users/user-id-1&quot;);</code></pre><h2>Pain points</h2><p>In our work towards automating case conversion within neeto, we encounteredseveral pain points.</p><h3>1. Manual work is involved</h3><p>During the rollout phase of our automated case conversion solution, there was anunavoidable requirement for manual intervention. As we transitioned the existingcode bases to incorporate the new mechanisms for automatic case conversionwithin Axios, each Axios call needed an adjustment to remove the manual caseconversion codes written before.</p><p>This stage demanded some manual work from our development teams. They updatedand modified existing Axios requests across multiple projects to ensure theyaligned with the new automated case conversion mechanism. While this manualeffort temporarily increased the workload, it was a necessary step to implement theautomated solution effectively across Neeto.</p><p>This phase highlighted the importance of a structured rollout plan andmeticulous attention to detail. Despite the initial manual workload, once thechanges were applied uniformly across the codebase, the benefits of automatedcase conversion quickly became evident, significantly reducing ongoing manualefforts and improving the overall efficiency of our development process.</p><h3>2. Serialization Issues</h3><p>As our initial implementation of automated case conversion, we used<code>keysToSnakeCase</code> method, which recursively transforms all the keys to snakecase for a given object. It internally used <code>transformObjectDeep</code> function torecursively traverse through each key-value pair inside an object fortransformation.</p><pre><code class="language-js">import { camelToSnakeCase } from &quot;@bigbinary/neeto-cist&quot;;const transformObjectDeep = (object, keyValueTransformer) =&gt; {  if (Array.isArray(object)) {    return object.map(obj =&gt;      transformObjectDeep(obj, keyValueTransformer, objectPreProcessor)    );  } else if (object === null || typeof object !== &quot;object&quot;) {    return object;  }  return Object.fromEntries(    Object.entries(object).map(([key, value]) =&gt;      keyValueTransformer(        key,        transformObjectDeep(value, keyValueTransformer, objectPreProcessor)      )    )  );};export const keysToSnakeCase = object =&gt;  transformObjectDeep(object, (key, value) =&gt; [camelToSnakeCase(key), value]);</code></pre><p>However, this recursive transformation approach led to a serialization issue,especially with objects that required special treatment, such as <code>dayjs</code> objectsrepresenting dates. The method treated these objects like any other JavaScriptobject, causing unexpected transformations and resulting in invalid payload datain some cases.</p><p>To mitigate these serialization issues and prevent interference with specificobject types, we enhanced the <code>transformObjectDeep</code> method to accommodate apreprocessor function for objects before the transformation:</p><pre><code class="language-js">const transformObjectDeep = (  object,  keyValueTransformer,  objectPreProcessor = undefined) =&gt; {  if (objectPreProcessor &amp;&amp; typeof objectPreProcessor === &quot;function&quot;) {    object = objectPreProcessor(object);  }  // Existing transformation logic};</code></pre><p>This modification allowed us to serialize objects before initiating thetransformation process. To facilitate this, we introduced a new method,<code>serializeKeysToSnakeCase</code>, incorporating the object preprocessor. For specificobject types requiring special serialization, such as <code>dayjs</code> objects, weleveraged the built-in <code>toJSON</code> method, allowing the object to transform itselfto its desired format, such as a date string:</p><pre><code class="language-js">import { transformObjectDeep, camelToSnakeCase } from &quot;@bigbinary/neeto-cist&quot;;export const serializeKeysToSnakeCase = object =&gt;  transformObjectDeep(    object,    (key, value) =&gt; [camelToSnakeCase(key), value],    object =&gt; (typeof object?.toJSON === &quot;function&quot; ? object.toJSON() : object)  );</code></pre><p>This resolved the serialization issue for the request payloads. Since theresponse is always in JSON format, all values are objects, arrays, orprimitives. It won't contain such 'magical' objects. So we need this logic onlyfor request interceptors.</p><h2>Conclusion</h2><p>In simplifying our web development workflow at Neeto, automating case conversionproved crucial. Despite challenges during implementation, refining our methodsstrengthened our system. By streamlining data translation and overcoming hurdleslike serialization issues, we've improved efficiency and compatibility acrossour ecosystem.</p><p>If you're starting a new project, adopting automated case conversion mechanismssimilar to what we've built in Axios can offer significant advantages.Implementing these standards from the beginning promotes consistency andsimplifies how data moves between your frontend and backend systems. Introducingthese practices early in your project's lifecycle help sidestep thedifficulties of adjusting existing code and establishing a unified conventionthroughout your project's structure.</p><p>For existing projects, adopting automated case conversion might initially comewith a cost. Introducing these changes requires careful planning and executionto minimize disruptions. The rollout process might necessitate manual updatesacross various parts of the codebase, leading to increased workload andpotential short-term setbacks.</p>]]></content>
    </entry>
     </feed>