<?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: Amartya Chowdhury</title>
    <description>The latest articles on DEV Community by Amartya Chowdhury (@aetherflux).</description>
    <link>https://dev.to/aetherflux</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%2F1203703%2F8dc4b75a-342c-418d-88f0-cddb051bbee7.png</url>
      <title>DEV Community: Amartya Chowdhury</title>
      <link>https://dev.to/aetherflux</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aetherflux"/>
    <language>en</language>
    <item>
      <title>You Don't Have to Grind LeetCode</title>
      <dc:creator>Amartya Chowdhury</dc:creator>
      <pubDate>Wed, 17 Sep 2025 15:23:57 +0000</pubDate>
      <link>https://dev.to/aetherflux/you-dont-have-to-grind-leetcode-3a4o</link>
      <guid>https://dev.to/aetherflux/you-dont-have-to-grind-leetcode-3a4o</guid>
      <description>&lt;p&gt;Yes, you read it right. Everyone says "you should do 500 problems on LeetCode at least". And sure, to some extent, it is helpful. But it's not everything. You don't need to follow the same path if you see a bunch of people on Twitter/Linkedin doing a "100 days of code" challenge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Are you inconsistent, no matter how hard you try?
&lt;/h3&gt;

&lt;p&gt;Have you ever felt like no matter how much you try to be consistent, try to do at least one LeetCode problem a day, you just can't keep it up for more than a week? Do you have to force yourself just to be consistent?&lt;/p&gt;

&lt;p&gt;So let's look at it from a different perspective. Let's say, like me, you are someone who hates the subject of biology. I have always hated that subject, to the point that I couldn't bring myself to keep my eyes open for 2 minutes without trying to force myself awake again. And I was a student who never slept in study sessions. No matter how much I forced myself to study biology, I could never do it well.&lt;/p&gt;

&lt;p&gt;Sounds similar? Because it is. Maybe underneath all of the Twitter/Linkedin posts and flexes of LeetCode grinds and coding challenges, it has never even crossed your mind that maybe this LeetCode grind is just not what you love.&lt;/p&gt;

&lt;h3&gt;
  
  
  No LeetCode? Then what?
&lt;/h3&gt;

&lt;p&gt;It is very much possible that you are the kind of person who just isn't built for LeetCode grinds. And that isn't necessarily a bad thing; it's just a different style. Maybe you are built for LeetCode grinds, or maybe you are someone who likes to see immediate results, someone who prefers building a website or an app to see their work in action, someone who likes to handle domains and manage servers, maybe even someone who's just a complete nerd that likes Linux and Vim (don't worry, I'm with you 😔).&lt;/p&gt;

&lt;p&gt;Everybody has a different thing they love. Taking myself as an example again, I was never someone who liked solving LeetCode problems. That was primarily because I couldn't see any effects of my code immediately. I had always preferred building websites where I can see the fruits of my action. Even now, I am very development-oriented, although I don't really like frontend dev (sorry fellow frontend devs 😔). I currently build backend systems and infra/devtools, but the concept is still the same: &lt;strong&gt;building something actually useful and not just blindly solving random problems&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  So, is LeetCode (or any problem solving) useless?
&lt;/h3&gt;

&lt;p&gt;This is where most people misunderstand. I am not saying that LeetCode grind, or any kind of problem solving, is useless. It's the most important, in fact. DSA is a major factor in you becoming a better developer. &lt;/p&gt;

&lt;p&gt;However, it's not essential that you learn DSA through just LeetCode problems. DSA shines the most when it's applied in real-life products. For example, build something yourself, maybe a backend or some library, and experiment about how to make it more efficient. Maybe learn about which algorithms would be better and more efficient, or just design one yourself. Maybe use a linked list instead of an array in some cases. That is where DSA shines. That is where real &lt;strong&gt;problem-solving&lt;/strong&gt; takes place.&lt;/p&gt;

&lt;p&gt;I'll put a little flex of myself again. I was working on my backend framework (&lt;em&gt;Rensa&lt;/em&gt;), and my first draft of the routing system used plain arrays to store routes and route handlers. As a result, whenever a user would hit a route on the server, it would take &lt;strong&gt;O(n)&lt;/strong&gt; time to search for the route (&lt;em&gt;n&lt;/em&gt; is the number of routes) and it's handler and call it. Very inefficient for good backend servers. So, I researched a bit and stumbled upon &lt;strong&gt;Tries&lt;/strong&gt;. Implemented route storage with that, and boom, the time complexity reduced to &lt;strong&gt;O(l)&lt;/strong&gt;, where &lt;em&gt;l&lt;/em&gt; is the length of route. It doesn't depend on the number of routes registered, which is better as a server increases in size. Then a sudden enlightenment hit me all of a sudden, and I implemented a hybrid &lt;strong&gt;Trie+HashMap&lt;/strong&gt; for storing routes. Now, although theoretically the time complexity was still &lt;strong&gt;O(l)&lt;/strong&gt;, but for completely static routes (like /home/dashboard, unlike /user/:userId), it practically worked in &lt;strong&gt;O(1)&lt;/strong&gt; (constant) time, thanks to the newly introduced HashMap. (Read more about the entire approach &lt;a href="https://dev.to/aetherflux/the-hidden-complexity-of-routing-why-your-requests-take-longer-than-they-should-5bbf"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;As you can see, you can start something small with just as much knowledge as you have right now, and with time and research you can keep on improving your solutions bit-by-bit. &lt;/p&gt;

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

&lt;p&gt;The conclusion is just that &lt;strong&gt;you don't need to feel guilty if you can't stay consistent, you just need to change your ways&lt;/strong&gt;. Sure, LeetCode problems are definitely not useless and they do teach you about how many commonly encountered problems can be solved. But it's not everything, because ultimately, you will be having to build systems and not be only solving problems all your career.&lt;/p&gt;

&lt;p&gt;So, the next time you feel demotivated because of inconsistency, just remember this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have to force yourself to do something, it probably isn't for you. Time to change your ways.&lt;br&gt;
&lt;strong&gt;Consistency will automatically follow you if you're doing something you truly love.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Time for some personal promotion, so before you leave, make sure to follow me on &lt;a href="https://x.com/aetheros__" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://linkedin.com/in/amartya-chowdhury" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>motivation</category>
      <category>programming</category>
      <category>leetcode</category>
    </item>
    <item>
      <title>Building Profig - A Config Framework</title>
      <dc:creator>Amartya Chowdhury</dc:creator>
      <pubDate>Thu, 07 Aug 2025 15:33:37 +0000</pubDate>
      <link>https://dev.to/aetherflux/building-profig-a-config-framework-36o1</link>
      <guid>https://dev.to/aetherflux/building-profig-a-config-framework-36o1</guid>
      <description>&lt;p&gt;I've worked with config files for a long time. Be it for my own tools/projects or for using it for other purposes, I have needed to manage configs manually for a long time. Until I discovered that there exist literal config managers, and that I had been wasting my efforts for absolutely no reason.&lt;/p&gt;

&lt;p&gt;I found that there were a bunch of good options available for config managers in JavaScript (NPM). However, the same is not the case for Rust. Here, there are limited options, popular ones being &lt;code&gt;config&lt;/code&gt;, &lt;code&gt;config-manager&lt;/code&gt; and &lt;code&gt;figment&lt;/code&gt;. And so I set out to work on a new project, and here it is:&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Profig?
&lt;/h2&gt;

&lt;p&gt;Introducing &lt;strong&gt;Profig&lt;/strong&gt;, a config &lt;em&gt;framework&lt;/em&gt;, that removes the &lt;em&gt;Con&lt;/em&gt; in &lt;em&gt;Config&lt;/em&gt;. This is still in very early development stages, and I've only released just &lt;code&gt;v0.1&lt;/code&gt;, but I think it's still usable in small and maybe even medium sized projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;p&gt;Profig is currently &lt;code&gt;v0.1&lt;/code&gt;, and it has the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Macros like &lt;code&gt;#[derive(Profig)]&lt;/code&gt; and &lt;code&gt;#[profig(...)]&lt;/code&gt; to define config schema structs&lt;/li&gt;
&lt;li&gt;Enforce only certain file formats to be allowed to load data from, using &lt;code&gt;#[profig(format="json,toml")]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Every field of the struct will have its own metadata, defined via &lt;code&gt;#[profig(min="..", max="..", default="..", regex=r"..", doc="..")]&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Data can be loaded from any file using &lt;code&gt;AppConfig::load("filename.ext")&lt;/code&gt; (assuming AppConfig is the name of the struct defined), and it returns an object of type AppConfig&lt;/li&gt;
&lt;li&gt;It validates every field data according to the metadata (&lt;code&gt;min&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;, &lt;code&gt;regex&lt;/code&gt; etc.) and fills a field with the &lt;code&gt;default&lt;/code&gt; value if applicable&lt;/li&gt;
&lt;li&gt;Sample config files can be generated via &lt;code&gt;AppConfig::sample_config("sample.yaml")&lt;/code&gt; using the data available in the metadata of the fields (defined using &lt;code&gt;#[profig(...)]&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Documentation can be generated automatically using &lt;code&gt;AppConfig::generate_docs("docs.md")&lt;/code&gt; which generates a markdown file using the &lt;code&gt;doc&lt;/code&gt; metadata of every field&lt;/li&gt;
&lt;li&gt;Multiple formats: JSON, TOML, YAML (all as their own features)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;

&lt;p&gt;All these features can seem confusing and overwhelming at first, even though they aim to greatly enhance DX. So, let's do a bit of practical.&lt;/p&gt;

&lt;p&gt;Let's imagine a situation where we need the user to define a config file which contains some data like host name, port number, user email, and the number of worker threads. The user may have a JSON or a YAML file as a config file. Using this data, our Rust code is supposed to authenticate/validate the details and then start a server or do something else, as required. Suppose that we are to build a CLI, and we need the details from a config file, as mentioned. Let's see how simple it is to achieve with &lt;strong&gt;Profig&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before anything else, let us first add the crate to our project. Since we need JSON and YAML configs, we will enable those features while installing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo add profig &lt;span class="nt"&gt;--features&lt;/span&gt; &lt;span class="s2"&gt;"json,yaml"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we define a schema for the config file. To define the schema, we use the attributes provided by Profig as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Profig)]&lt;/span&gt;
&lt;span class="nd"&gt;#[profig(format=&lt;/span&gt;&lt;span class="s"&gt;"json, yaml"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;HostConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;#[profig(min=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;max=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;doc=&lt;/span&gt;&lt;span class="s"&gt;"Number of worker threads"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
  &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="nd"&gt;#[profig(default=&lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;doc=&lt;/span&gt;&lt;span class="s"&gt;"Name of the host"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
  &lt;span class="n"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="nd"&gt;#[profig(min=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;max=&lt;/span&gt;&lt;span class="s"&gt;"65536"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;doc=&lt;/span&gt;&lt;span class="s"&gt;"Port number to listen to"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
  &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="nd"&gt;#[profig(regex=&lt;/span&gt;&lt;span class="s"&gt;r"^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;doc=&lt;/span&gt;&lt;span class="s"&gt;"Email address of the user"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
  &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&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 all we need to do in order to define the schema/format of the config files. We specified formats as &lt;code&gt;json&lt;/code&gt; and &lt;code&gt;yaml&lt;/code&gt; as those are the only ones allowed. Now to read data from a file, say &lt;code&gt;config.yaml&lt;/code&gt;, we can do so as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;confData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;HostConfig&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"config.yaml"&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="c1"&gt;// All data can now be accessed as confData.email, confData.host etc&lt;/span&gt;
  &lt;span class="c1"&gt;// because this returns an object of type HostConfig.&lt;/span&gt;
  &lt;span class="c1"&gt;// You can use this data for any further logic implementation&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voila! You have successfully loaded and used data from config files!&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample Config
&lt;/h3&gt;

&lt;p&gt;You can also generate a sample config file in a single line, using the following function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;HostConfig&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sample_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sample.json"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create the following type of sample file (JSON here):&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"threads"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REQUIRED; must match ^[a-z0-9._%+-]+@[a-z0-9.-]+&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;[a-z]{2,4}$"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Documentation Generation
&lt;/h3&gt;

&lt;p&gt;That's not all. You can also generate a documentation for your defined config structure in a single line! Just call the following method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;HostConfig&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;generate_doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"docs.md"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it will generate you a &lt;code&gt;markdown&lt;/code&gt; file filled with data like field name, field data type, and a field help/doc line if provided (via the &lt;code&gt;doc="..."&lt;/code&gt; value in the field-level metadata).&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠 Tech Dive
&lt;/h2&gt;

&lt;p&gt;For the bit more nerdy humans like myself, let's talk a bit about the tech. This project uses Rust (no s**t Sherlock), along with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serde, serde_json for storing and validating the data&lt;/li&gt;
&lt;li&gt;serde_json, serde_yaml and toml crates to load data from different config file types&lt;/li&gt;
&lt;li&gt;Procedural macros to make the &lt;code&gt;#[derive(Profig)]&lt;/code&gt; and &lt;code&gt;#[profig(...)]&lt;/code&gt; attributes to make DX smoother&lt;/li&gt;
&lt;li&gt;Feature flags for every file format to avoid unnecessarily bloating the crate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is an architecture/design of the entire working or flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.licdn.com%2Fdms%2Fimage%2Fv2%2FD5622AQFvA8-_ZLcwPA%2Ffeedshare-shrink_800%2FB56Zh63vkHG4Ak-%2F0%2F1754408098595%3Fe%3D1757548800%26v%3Dbeta%26t%3DOFh-y1BfHQLSYmHTs2BvdhDTENfqoF3to6LSMMHiWvo" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.licdn.com%2Fdms%2Fimage%2Fv2%2FD5622AQFvA8-_ZLcwPA%2Ffeedshare-shrink_800%2FB56Zh63vkHG4Ak-%2F0%2F1754408098595%3Fe%3D1757548800%26v%3Dbeta%26t%3DOFh-y1BfHQLSYmHTs2BvdhDTENfqoF3to6LSMMHiWvo" alt="profig architecture" width="800" height="251"&gt;&lt;/a&gt;️ &lt;/p&gt;

&lt;h2&gt;
  
  
  Final Notes
&lt;/h2&gt;

&lt;p&gt;All in all, Profig is a config framework that I plan to keep building and improving as time sees. It is in very early stages right now, being just &lt;code&gt;v0.1&lt;/code&gt;, so there will be quite some changes before even &lt;code&gt;Profig v1&lt;/code&gt; is launched.&lt;/p&gt;

&lt;p&gt;In the meanwhile, I would love any and all feedbacks and advice.&lt;/p&gt;

&lt;p&gt;Please do try it for yourself if possible:&lt;br&gt;
🦀 &lt;a href="https://crates.io/crates/profig" rel="noopener noreferrer"&gt;Crates.io&lt;/a&gt;&lt;br&gt;
💻 &lt;a href="https://github.com/aether-flux/profig" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more updates, follow me on:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/amartya-chowdhury" rel="noopener noreferrer"&gt;LINKEDIN&lt;/a&gt;&lt;br&gt;
&lt;a href="https://x.com/aetheros__" rel="noopener noreferrer"&gt;TWITTER&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Building Profig - A Config Framework</title>
      <dc:creator>Amartya Chowdhury</dc:creator>
      <pubDate>Thu, 07 Aug 2025 15:33:37 +0000</pubDate>
      <link>https://dev.to/aetherflux/building-profig-a-config-framework-1cca</link>
      <guid>https://dev.to/aetherflux/building-profig-a-config-framework-1cca</guid>
      <description>&lt;p&gt;I've worked with config files for a long time. Be it for my own tools/projects or for using it for other purposes, I have needed to manage configs manually for a long time. Until I discovered that there exist literal config managers, and that I had been wasting my efforts for absolutely no reason.&lt;/p&gt;

&lt;p&gt;I found that there were a bunch of good options available for config managers in JavaScript (NPM). However, the same is not the case for Rust. Here, there are limited options, popular ones being &lt;code&gt;config&lt;/code&gt;, &lt;code&gt;config-manager&lt;/code&gt; and &lt;code&gt;figment&lt;/code&gt;. And so I set out to work on a new project, and here it is:&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Profig?
&lt;/h2&gt;

&lt;p&gt;Introducing &lt;strong&gt;Profig&lt;/strong&gt;, a config &lt;em&gt;framework&lt;/em&gt;, that removes the &lt;em&gt;Con&lt;/em&gt; in &lt;em&gt;Config&lt;/em&gt;. This is still in very early development stages, and I've only released just &lt;code&gt;v0.1&lt;/code&gt;, but I think it's still usable in small and maybe even medium sized projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;p&gt;Profig is currently &lt;code&gt;v0.1&lt;/code&gt;, and it has the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Macros like &lt;code&gt;#[derive(Profig)]&lt;/code&gt; and &lt;code&gt;#[profig(...)]&lt;/code&gt; to define config schema structs&lt;/li&gt;
&lt;li&gt;Enforce only certain file formats to be allowed to load data from, using &lt;code&gt;#[profig(format="json,toml")]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Every field of the struct will have its own metadata, defined via &lt;code&gt;#[profig(min="..", max="..", default="..", regex=r"..", doc="..")]&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Data can be loaded from any file using &lt;code&gt;AppConfig::load("filename.ext")&lt;/code&gt; (assuming AppConfig is the name of the struct defined), and it returns an object of type AppConfig&lt;/li&gt;
&lt;li&gt;It validates every field data according to the metadata (&lt;code&gt;min&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;, &lt;code&gt;regex&lt;/code&gt; etc.) and fills a field with the &lt;code&gt;default&lt;/code&gt; value if applicable&lt;/li&gt;
&lt;li&gt;Sample config files can be generated via &lt;code&gt;AppConfig::sample_config("sample.yaml")&lt;/code&gt; using the data available in the metadata of the fields (defined using &lt;code&gt;#[profig(...)]&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Documentation can be generated automatically using &lt;code&gt;AppConfig::generate_docs("docs.md")&lt;/code&gt; which generates a markdown file using the &lt;code&gt;doc&lt;/code&gt; metadata of every field&lt;/li&gt;
&lt;li&gt;Multiple formats: JSON, TOML, YAML (all as their own features)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;

&lt;p&gt;All these features can seem confusing and overwhelming at first, even though they aim to greatly enhance DX. So, let's do a bit of practical.&lt;/p&gt;

&lt;p&gt;Let's imagine a situation where we need the user to define a config file which contains some data like host name, port number, user email, and the number of worker threads. The user may have a JSON or a YAML file as a config file. Using this data, our Rust code is supposed to authenticate/validate the details and then start a server or do something else, as required. Suppose that we are to build a CLI, and we need the details from a config file, as mentioned. Let's see how simple it is to achieve with &lt;strong&gt;Profig&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before anything else, let us first add the crate to our project. Since we need JSON and YAML configs, we will enable those features while installing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo add profig &lt;span class="nt"&gt;--features&lt;/span&gt; &lt;span class="s2"&gt;"json,yaml"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we define a schema for the config file. To define the schema, we use the attributes provided by Profig as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[derive(Profig)]&lt;/span&gt;
&lt;span class="nd"&gt;#[profig(format=&lt;/span&gt;&lt;span class="s"&gt;"json, yaml"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;HostConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;#[profig(min=&lt;/span&gt;&lt;span class="s"&gt;"4"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;max=&lt;/span&gt;&lt;span class="s"&gt;"10"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;doc=&lt;/span&gt;&lt;span class="s"&gt;"Number of worker threads"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
  &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="nd"&gt;#[profig(default=&lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;doc=&lt;/span&gt;&lt;span class="s"&gt;"Name of the host"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
  &lt;span class="n"&gt;hostname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="nd"&gt;#[profig(min=&lt;/span&gt;&lt;span class="s"&gt;"1"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;max=&lt;/span&gt;&lt;span class="s"&gt;"65536"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;doc=&lt;/span&gt;&lt;span class="s"&gt;"Port number to listen to"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
  &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="nd"&gt;#[profig(regex=&lt;/span&gt;&lt;span class="s"&gt;r"^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"&lt;/span&gt;&lt;span class="nd"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;doc=&lt;/span&gt;&lt;span class="s"&gt;"Email address of the user"&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
  &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&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 all we need to do in order to define the schema/format of the config files. We specified formats as &lt;code&gt;json&lt;/code&gt; and &lt;code&gt;yaml&lt;/code&gt; as those are the only ones allowed. Now to read data from a file, say &lt;code&gt;config.yaml&lt;/code&gt;, we can do so as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;confData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;HostConfig&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"config.yaml"&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="c1"&gt;// All data can now be accessed as confData.email, confData.host etc&lt;/span&gt;
  &lt;span class="c1"&gt;// because this returns an object of type HostConfig.&lt;/span&gt;
  &lt;span class="c1"&gt;// You can use this data for any further logic implementation&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voila! You have successfully loaded and used data from config files!&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample Config
&lt;/h3&gt;

&lt;p&gt;You can also generate a sample config file in a single line, using the following function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;HostConfig&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sample_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"sample.json"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create the following type of sample file (JSON here):&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"threads"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hostname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REQUIRED; must match ^[a-z0-9._%+-]+@[a-z0-9.-]+&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;[a-z]{2,4}$"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Documentation Generation
&lt;/h3&gt;

&lt;p&gt;That's not all. You can also generate a documentation for your defined config structure in a single line! Just call the following method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nn"&gt;HostConfig&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;generate_doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"docs.md"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it will generate you a &lt;code&gt;markdown&lt;/code&gt; file filled with data like field name, field data type, and a field help/doc line if provided (via the &lt;code&gt;doc="..."&lt;/code&gt; value in the field-level metadata).&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠 Tech Dive
&lt;/h2&gt;

&lt;p&gt;For the bit more nerdy humans like myself, let's talk a bit about the tech. This project uses Rust (no s**t Sherlock), along with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serde, serde_json for storing and validating the data&lt;/li&gt;
&lt;li&gt;serde_json, serde_yaml and toml crates to load data from different config file types&lt;/li&gt;
&lt;li&gt;Procedural macros to make the &lt;code&gt;#[derive(Profig)]&lt;/code&gt; and &lt;code&gt;#[profig(...)]&lt;/code&gt; attributes to make DX smoother&lt;/li&gt;
&lt;li&gt;Feature flags for every file format to avoid unnecessarily bloating the crate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is an architecture/design of the entire working or flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.licdn.com%2Fdms%2Fimage%2Fv2%2FD5622AQFvA8-_ZLcwPA%2Ffeedshare-shrink_800%2FB56Zh63vkHG4Ak-%2F0%2F1754408098595%3Fe%3D1757548800%26v%3Dbeta%26t%3DOFh-y1BfHQLSYmHTs2BvdhDTENfqoF3to6LSMMHiWvo" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.licdn.com%2Fdms%2Fimage%2Fv2%2FD5622AQFvA8-_ZLcwPA%2Ffeedshare-shrink_800%2FB56Zh63vkHG4Ak-%2F0%2F1754408098595%3Fe%3D1757548800%26v%3Dbeta%26t%3DOFh-y1BfHQLSYmHTs2BvdhDTENfqoF3to6LSMMHiWvo" alt="profig architecture" width="800" height="251"&gt;&lt;/a&gt;️ &lt;/p&gt;

&lt;h2&gt;
  
  
  Final Notes
&lt;/h2&gt;

&lt;p&gt;All in all, Profig is a config framework that I plan to keep building and improving as time sees. It is in very early stages right now, being just &lt;code&gt;v0.1&lt;/code&gt;, so there will be quite some changes before even &lt;code&gt;Profig v1&lt;/code&gt; is launched.&lt;/p&gt;

&lt;p&gt;In the meanwhile, I would love any and all feedbacks and advice.&lt;/p&gt;

&lt;p&gt;Please do try it for yourself if possible:&lt;br&gt;
🦀 &lt;a href="https://crates.io/crates/profig" rel="noopener noreferrer"&gt;Crates.io&lt;/a&gt;&lt;br&gt;
💻 &lt;a href="https://github.com/aether-flux/profig" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more updates, follow me on:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/amartya-chowdhury" rel="noopener noreferrer"&gt;LINKEDIN&lt;/a&gt;&lt;br&gt;
&lt;a href="https://x.com/aetheros__" rel="noopener noreferrer"&gt;TWITTER&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>tooling</category>
    </item>
    <item>
      <title>I Got Tired of Repeating the Same Commands, so I Built Jido - a Workflow Automation CLI</title>
      <dc:creator>Amartya Chowdhury</dc:creator>
      <pubDate>Fri, 16 May 2025 18:51:44 +0000</pubDate>
      <link>https://dev.to/aetherflux/i-got-tired-of-repeating-the-same-commands-so-i-built-jido-a-workflow-automation-cli-2d2h</link>
      <guid>https://dev.to/aetherflux/i-got-tired-of-repeating-the-same-commands-so-i-built-jido-a-workflow-automation-cli-2d2h</guid>
      <description>&lt;p&gt;As a developer, you may have had moments where you find yourself running the same bunch of commands repeatedly. For example, bumping &lt;code&gt;package.json&lt;/code&gt; version, pushing to git, and publishing to NPM, whenever you wanna ship a new version of your NPM package. &lt;/p&gt;

&lt;p&gt;I was facing the same issue. And given how lazy my brain is, I wanted to make this easier and simpler. So, I built Jido.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Jido?
&lt;/h2&gt;

&lt;p&gt;Jido is a workflow automation CLI, where you can define your workflows (called &lt;code&gt;flows&lt;/code&gt;) in a config file, and run them using &lt;code&gt;npx jido flow &amp;lt;flowname&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The config file is a &lt;code&gt;jido.config.js&lt;/code&gt; in the project root. So, custom JS logic is also applicable, unlike Bash scripts.&lt;/p&gt;

&lt;p&gt;Get started with &lt;code&gt;jido&lt;/code&gt; by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; jido
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Config File
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;jido.config.js&lt;/code&gt; file call the &lt;code&gt;jido()&lt;/code&gt; function and export it by default. It takes in an object as argument, which has the key &lt;code&gt;flows&lt;/code&gt; that holds an array of objects, each object defining a &lt;code&gt;flow&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Every &lt;code&gt;flow&lt;/code&gt; has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: Name of the flow&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt; (Optional): A short description about the flow&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;steps&lt;/code&gt;: Array of objects, each object defining what each step would do&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each &lt;code&gt;step&lt;/code&gt; is of the following form:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;run&lt;/code&gt;: The command to be run at this step (eg, 'npm run dev' or 'git push' etc).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onStart, onSuccess, onFailure&lt;/code&gt;: Optional hooks. These are functions that will be called on start, success and failure of the step.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;plugins&lt;/code&gt;: An array of objects, where each object is a plugin. We'll talk more about this in a while.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To scaffold a basic config file, run &lt;code&gt;npx jido init&lt;/code&gt;. It'll generate the following config file:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;jido&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jido&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/*
* Define your workflows here.
* Each flow is a series of steps with commands to run and optional hooks (onStart, onSuccess, etc) to execute.
*/&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;flows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;run&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Run the project&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;npm install&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;onStart&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Installing dependencies...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="na"&gt;onSuccess&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dependencies installed!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;  &lt;span class="c1"&gt;// Any plugins go here&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;npm run dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;onStart&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Starting dev server...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;  &lt;span class="c1"&gt;// Any plugins go here&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;jido&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Plugins
&lt;/h3&gt;

&lt;p&gt;Now, another fun part of Jido. Plugins. A plugin is essentially an object of the following type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Plugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;onStart&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Hook&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;onSuccess&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Hook&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;onFailure&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Hook&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;Basically, its an object with any or all of these hooks, which are attached to the &lt;code&gt;step&lt;/code&gt; where the plugin is attached to.&lt;/p&gt;

&lt;p&gt;However, the recommended way of writing a plugin is to write it in a function which returns an object of the above type. This allows in custom and argument-dependent functionality of a plugin.&lt;/p&gt;

&lt;p&gt;For example:&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="c1"&gt;// Plugin function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myPlugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;onStart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`[myPlugin] Hello, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;! Step started...`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// In a step in the config file:&lt;/span&gt;
&lt;span class="nl"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;myPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aether-flux&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="c1"&gt;// In another step:&lt;/span&gt;
&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;myPlugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Now, Where Do You Use Jido?
&lt;/h3&gt;

&lt;p&gt;Well, one of the use-cases is when publishing a new version of a package to NPM or anywhere else. That was the reason why I even thought of making this CLI.&lt;/p&gt;

&lt;p&gt;There are many other applications as well. For instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy to vercel after a successful build.&lt;/li&gt;
&lt;li&gt;Clean + Reset project state before testing.&lt;/li&gt;
&lt;li&gt;Run local dev with custom logging and/or analytics tracking.&lt;/li&gt;
&lt;li&gt;Alert team (Slack, Discord, etc) after a successful build and deploy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And anywhere else really, where you find yourself running the same bunch of tasks over and over again.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, What Do You Think?
&lt;/h2&gt;

&lt;p&gt;I hope Jido can simplify repetitive tasks for many devs out there, thus allowing them to focus more on the fun part (aka 'coding') rather than spending so much time just pushing to github and building and deploying and all that.&lt;/p&gt;

&lt;p&gt;Do give it a chance in your workflow once. I'm sure it'd work wonders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BTW, publishing any new version of Jido is being automated by &lt;code&gt;jido&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/aether-flux/jido" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FStar%2520the%2520Repo-%25F0%259F%258C%259F-brightgreen%3Fstyle%3Dfor-the-badge" alt="⭐ Star the Repo" width="156" height="28"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://npmjs.com/package/jido" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FGet%2520the%2520CLI%2520now-%25F0%259F%2593%25A6-blue%3Fstyle%3Dfor-the-badge" alt="📦 Get the CLI now" width="171" height="28"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>⚒ The Hidden Complexity Of Routing: Why Your Requests Take Longer Than They Should</title>
      <dc:creator>Amartya Chowdhury</dc:creator>
      <pubDate>Wed, 26 Feb 2025 17:08:59 +0000</pubDate>
      <link>https://dev.to/aetherflux/the-hidden-complexity-of-routing-why-your-requests-take-longer-than-they-should-5bbf</link>
      <guid>https://dev.to/aetherflux/the-hidden-complexity-of-routing-why-your-requests-take-longer-than-they-should-5bbf</guid>
      <description>&lt;p&gt;When you type a URL and hit Enter, does it just magically find what to load in the page? Or when building your own server, just adding &lt;code&gt;app.get("/user/:id")&lt;/code&gt; will do all the magic itself?&lt;/p&gt;

&lt;p&gt;The simple answer is &lt;strong&gt;NO&lt;/strong&gt;. We usually never think much about routing and how it works, but its one of the major factors that affect the performance of a framework and a server.&lt;/p&gt;

&lt;h2&gt;
  
  
  😮‍💨 The Normal Approach
&lt;/h2&gt;

&lt;p&gt;The simplest way we all think first when asked about how to implement routing is to use a basic &lt;code&gt;for&lt;/code&gt; loop.&lt;br&gt;
1️⃣ Store the routes in an array.&lt;br&gt;
2️⃣ When a request is made, search for that route in the array using a for loop.&lt;br&gt;
3️⃣ If the route is found, the corresponding logic is executed.&lt;/p&gt;

&lt;p&gt;The problem? &lt;strong&gt;Speed&lt;/strong&gt;.&lt;br&gt;
Imagine a huge server with 1000+ routes. Then, to search for a specific route using this approach, what is the time required? &lt;strong&gt;O(n)&lt;/strong&gt;, &lt;code&gt;n&lt;/code&gt; being the &lt;code&gt;number of routes&lt;/code&gt;, i.e. 1000 here. That's a huge blow to the performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 The Better Approach
&lt;/h2&gt;

&lt;p&gt;You may be wondering, what should be done then? The answer lies in a magical little data structure, &lt;strong&gt;Trie&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdig1f799xd5d2xv93ljj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdig1f799xd5d2xv93ljj.png" alt="A diagram of a Trie" width="542" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A trie is basically a tree, which stores strings character-by-character, branching out whenever required (see image for better understanding). This reduces unnecessary comparisons, and you can just follow the path in the trie and find the matching path.&lt;/p&gt;

&lt;p&gt;The time complexity? Just a mere &lt;strong&gt;O(s)&lt;/strong&gt;, &lt;code&gt;s&lt;/code&gt; being the &lt;code&gt;length of route&lt;/code&gt;. So, if "/users" is the URL, &lt;code&gt;s&lt;/code&gt; is 6. No matter how many thousands of routes exist in the server, this approach only thinks about the route that is being requested, significantly reducing the time taken and enhancing performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔥 The Even Better Approach
&lt;/h2&gt;

&lt;p&gt;Now, is there any way to make this approach even more performant? The answer is to &lt;strong&gt;use a HashMap&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The trie is still going to store every route as it used to store earlier, character-by-character. However, this seems inefficient too, as most routes that get requested to a server are usually just static sites ("/users", "/dashboard" etc).&lt;/p&gt;

&lt;p&gt;So, we use a hashmap here. While storing the routes, we get all the static parts (words) of the route (ex 'dashboard' and 'home' in "/home/dashboard") and store them in the hashmap as keys. Their values will store the ending node of the trie where these static words end.&lt;/p&gt;

&lt;p&gt;When a request comes in, we first check if each part is static or dynamic. If its static, we instantly look in the hashmap first. If found, we get at which node of the trie it ends, and start searching from there again.&lt;/p&gt;

&lt;p&gt;This updated approach helps in jumping through the static words stored in the trie and only check for dynamic parts (like 'id' in "/user/:id").&lt;/p&gt;

&lt;p&gt;Since most requested routes contain static routes, this approach improves performance significantly. Although the time complexity is still O(s) theoretically, in practice, most routes, especially ones with just static parts, get searched in just &lt;strong&gt;O(1)&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  So What's The Takeaway?
&lt;/h2&gt;

&lt;p&gt;Routing isn't just about matching URLs to functions—it directly impacts server performance.&lt;/p&gt;

&lt;p&gt;❌ A simple for loop works, but it doesn’t scale well.&lt;br&gt;
✅ A Trie speeds things up, as lookup time depends only on route length.&lt;br&gt;
🚀 Combining it with a HashMap makes it even more efficient, allowing many static routes to be matched in near O(1) time.&lt;/p&gt;

&lt;p&gt;Many modern frameworks use optimized routing techniques under the hood, but knowing how they work gives you the power to build faster, more scalable applications. So, the next time you write app.get("/user/:id") you'll know the real magic behind it 😉&lt;/p&gt;

&lt;p&gt;For more informative stuff, follow me on &lt;a href="https://www.linkedin.com/in/amartya-chowdhury" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://x.com/aether__flux" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>⚡ Tired of DB Setups? Meet Swapp: The Universal DB Adapter</title>
      <dc:creator>Amartya Chowdhury</dc:creator>
      <pubDate>Sun, 09 Feb 2025 08:11:12 +0000</pubDate>
      <link>https://dev.to/aetherflux/tired-of-db-setups-meet-swapp-the-universal-db-adapter-105b</link>
      <guid>https://dev.to/aetherflux/tired-of-db-setups-meet-swapp-the-universal-db-adapter-105b</guid>
      <description>&lt;p&gt;Let's be honest: working with databases can be a pain. Whether its a SQL database like MySQL or PostgreSQL, or a NoSQL one like MongoDB, each has its own syntax, setup and quirks. Using any one of these involves copying and pasting tons of boilerplate code, and dealing with all sorts of dependencies.&lt;/p&gt;

&lt;p&gt;And don't even get me started on switching databases, especially from a SQL to a NoSQL one or vice-versa. Learning multiple different ways to write queries for the same basic operations gets annoying, right?&lt;/p&gt;

&lt;p&gt;That's where Swapp comes in!&lt;/p&gt;

&lt;p&gt;Imagine setting up a database with just one statement, and use one query language for both SQL and NoSQL databases. Sounds like a dream? Well, it just got real!&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Swapp.js is live!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/aether-flux/swappjs" rel="noopener noreferrer"&gt;🔗 GitHub Repo&lt;/a&gt; | &lt;a href="https://www.npmjs.com/package/swapp.js" rel="noopener noreferrer"&gt;📦 NPM Package&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;🚀 Swapp.js just launched on &lt;a href="https://www.producthunt.com/posts/swapp-js" rel="noopener noreferrer"&gt;Product Hunt!&lt;/a&gt; and &lt;a href="https://peerlist.io/neobius/project/swappjs" rel="noopener noreferrer"&gt;Peerlist&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is Swapp?&lt;/li&gt;
&lt;li&gt;
How to use Swapp?

&lt;ul&gt;
&lt;li&gt;Installation&lt;/li&gt;
&lt;li&gt;Configuring Your Database&lt;/li&gt;
&lt;li&gt;Basic CRUD Operations&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Why use Swapp?&lt;/li&gt;
&lt;li&gt;
Conclusion

&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  What is Swapp?
&lt;/h2&gt;

&lt;p&gt;Swapp is an easy-to-use database abstraction layer for Node.js. It connects to both SQL (like Supabase) and NoSQL (like MongoDB) databases using a simple, unified interface. The beauty of Swapp is that it lets you use a universal query language - think SQL-like queries - across both SQL and NoSQL databases. No more changing the entirety of your code just to switch from a SQL to a NoSQL database (or the other way around).&lt;/p&gt;

&lt;p&gt;Here's what Swapp provides you with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skip the tedious database setup process.&lt;/li&gt;
&lt;li&gt;Write queries in a SQL-like syntax that works across both MongoDB and Supabase (and more databases getting support soon).&lt;/li&gt;
&lt;li&gt;Focus on building your app, not on configuring your database.&lt;/li&gt;
&lt;li&gt;Enjoy easy-to-understand API calls for CRUD operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Basically, it does the heavy-lifting so you don't have to. Just configure Swapp, and then you can start building your app's features immediately. Swapp will take care of setting up the database for you.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to use Swapp?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;Installing Swapp is really easy. Just download it from npm, and you're set to go!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install swapp.js --legacy-peer-deps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add swapp.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuring Your Database
&lt;/h3&gt;

&lt;p&gt;Right now, Swapp supports MongoDB and Supabase. More databases are currently in development.&lt;/p&gt;

&lt;p&gt;If you're using MongoDB:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Swapp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;mongodb-connection-string&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;dbName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;database-name&amp;gt;&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;In case you use Supabase:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Swapp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;supabase&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;supabaseKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;Supabase-Key&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;supabaseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;Supabase-URL&amp;gt;&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;h3&gt;
  
  
  Basic CRUD Operations
&lt;/h3&gt;

&lt;p&gt;Most of the basic CRUD operations work just as expected. For example, to save data to the database:&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;collection/table name&amp;gt;&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now comes the fun part: the queries. Look at this example:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;collection/table name&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="s1"&gt;WHERE name = "John"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This searches for entries in the database with name = "John". Classic SQL-like query. The catch? This works seamlessly, whether you're using a SQL database (like Supabase) or a NoSQL one (like MongoDB)!&lt;/p&gt;

&lt;p&gt;Similarly, there are functions for db.update() and db.delete() as well. Check out the GitHub repository of Swapp for more detailed documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Swapp?
&lt;/h2&gt;

&lt;p&gt;If you're still unsure why you should use Swapp when there are so many database packages out there, let me try changing your mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Save Time:&lt;/strong&gt; No more memorizing different query languages for different databases. Swapp lets you focus on building your app, instead of worrying about database setups and queries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQL and NoSQL in One Package:&lt;/strong&gt; Swapp gives you the flexibility to use both SQL and NoSQL databases. If you wanna try out MongoDB for some flexible data storage and then shift to Supabase for a more structured data, Swapp lets you do that easily by changing just a single statement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ideal for MVPs and Prototyping:&lt;/strong&gt; If you're building an MVP or a prototype and don't want to be bogged down by database setup, Swapps lets you just plug in and get started quickly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simple, Intuitive API:&lt;/strong&gt; CRUD operations? Check. Universal queries? Check. But still easy to work with. You won't need to read through pages of documentation to get a simple query running.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Swapp is here to make your life easier. Whether you're new to databases or have been wrangling them for years, this tool can save you a ton of time and effort.&lt;/p&gt;

&lt;p&gt;So, why not give it a try? You'll be up and running in minutes, and you can spend your valuable time actually building your app.&lt;/p&gt;

&lt;p&gt;Check out the  &lt;a href="https://github.com/aether-flux/swappjs" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;  and leave a star if you found Swapp to be actually helpful in your development workflow. Feel free to leave any feedback and suggestions you may have, I am always open to new ideas.&lt;/p&gt;

&lt;p&gt;Let's swap out the complexity and start building!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Create your own Event Scheduling API using Express and Supabase</title>
      <dc:creator>Amartya Chowdhury</dc:creator>
      <pubDate>Mon, 04 Nov 2024 15:51:54 +0000</pubDate>
      <link>https://dev.to/aetherflux/create-your-own-event-scheduling-api-using-express-and-supabase-2c40</link>
      <guid>https://dev.to/aetherflux/create-your-own-event-scheduling-api-using-express-and-supabase-2c40</guid>
      <description>&lt;p&gt;Ever needed a platform to manage your club's events? Or perhaps schedule meetings in your office? But in search of affordable platforms, you get lost in the numerous options presented to you? Or maybe you just want to organize your life better and schedule when you have to attend which events?&lt;/p&gt;

&lt;p&gt;Follow this post through the end, and you'll end up with a basic event scheduling API where all basic features like event creation and registration will be available.&lt;/p&gt;

&lt;p&gt;The GitHub repository for this project is at &lt;a href="https://github.com/xerctia/gatherly" rel="noopener noreferrer"&gt;https://github.com/xerctia/gatherly&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Express?
&lt;/h2&gt;

&lt;p&gt;Express is a Javascript framework for setting up and building servers to handle various kinds of requests like GET, POST etc. Express is one of the most popularly used backend frameworks, and is also one of the easiest framework for beginners to start with. In this blog, we will be using Express for making our server and setting up the required endpoints.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is PostgreSQL?
&lt;/h2&gt;

&lt;p&gt;PostgreSQL is an open-source relational database management system (RDBMS), known for its reliability, scalability, and support for complex queries. It offers advanced features like support for JSON data, full-text search, and extensibility, making it versatile for both small projects and large-scale applications. PostgreSQL is popular among developers and is valued for its robust performance.&lt;/p&gt;

&lt;p&gt;There are many PostgreSQL providers available on the web that allow usage of a PostgreSQL database, some free of cost and some with a paid plan. In this project, we will be using Supabase and its database as our PostgreSQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the project
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create a folder for this project. I will name it Gatherly, which is the name I've decided.&lt;/li&gt;
&lt;li&gt;Set up Node and npm: &lt;code&gt;npm init -y&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Install Express and other required packages:
&lt;code&gt;npm install express dotenv cors pg&lt;/code&gt;
&lt;strong&gt;Note:&lt;/strong&gt; pg is the package used for using PostgreSQL in Node.js.&lt;/li&gt;
&lt;li&gt;Now create an &lt;code&gt;index.js&lt;/code&gt; file with the following boilerplate code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;exp&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="mi"&gt;3000&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="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencoded&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;extended&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&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;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, Gatherly!&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`server started on &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="s2"&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;Congrats! You have successfully set up a basic server in Express!&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Supabase with your Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Supabase setup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;a href="https://supabase.com" rel="noopener noreferrer"&gt;https://supabase.com&lt;/a&gt; and log into or create an account, and then create a new project with any name you see fit. I have named it Gatherly (obviously).&lt;/li&gt;
&lt;li&gt;Now go to the project dashboard and then navigate to Project Settings -&amp;gt; Database.&lt;/li&gt;
&lt;li&gt;In the starting of the page, a section of "Connection String" will be present. Click the Node.js tab here and copy the connection string and store it somewhere for now.&lt;/li&gt;
&lt;li&gt;Now go to the SQL Editor and run the following query to create an 'events' table:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;end_time&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Connecting database to Express
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Go to your project folder and create a file named &lt;code&gt;.env&lt;/code&gt;. Write &lt;code&gt;DATABASE_URL=&lt;/code&gt; and then paste the Connection String you copied earlier (Supabase setup: Step-3) and enclose it within double quotes. For example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL="postgresql://username:password@host:port/dbname"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create another JS file &lt;code&gt;db.js&lt;/code&gt; to set up and connect the PostgreSQL database.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pool&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&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;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;connectionString&lt;/span&gt;&lt;span class="p"&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;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rejectUnauthorized&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;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now lastly, we need to import this connected database to our main &lt;code&gt;index.js&lt;/code&gt; file.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./db&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations, you have successfully connected your Supabase database to your index.js file. We are now ready to start building the actual API endpoints.&lt;/p&gt;

&lt;h2&gt;
  
  
  API Endpoints
&lt;/h2&gt;

&lt;h3&gt;
  
  
  GET /events : Fetch all events
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a new GET method as follows:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/events&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="c1"&gt;// code to be written&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Inside this function, we will write the actual code that will fetch us the data. First of all, let's implement a try-catch block for better error handling.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// code to be written&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;e&lt;/span&gt;&lt;span class="p"&gt;)&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="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Database error.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 500 = Internal Server Error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;This format will be maintained for all the endpoints we will be building. Within the try block, we will write the code for the required feature.&lt;/li&gt;
&lt;li&gt;To fetch all the events in the database, we need to query the database and store it in a variable. Since we are following an asynchronous approach, so we need to use await to store the data correctly.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM events&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The output of this query, i.e. result, has an array of objects called 'rows'. Here, we need to return all the events, so we will just return the entire 'rows'.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 200 = OK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;With this, our first endpoint is ready! To test it out, you can go to the Table Editor at Supabase project's dashboard and add 2 or 3 events for testing purposes. The entire code for this endpoint is:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/events&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Getting all events&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM events&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 200 = OK&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;e&lt;/span&gt;&lt;span class="p"&gt;)&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="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Database error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 500 = Internal Server Error&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  POST /events : Create a new event
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;First of all, let's set up a basic boilerplate of an endpoint:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/events&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// code to be written&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;e&lt;/span&gt;&lt;span class="p"&gt;)&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="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to create event.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 500 = Internal Server Error&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;In this case, as we have some data we need from the user, we can define those outside of the try-catch block.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end_time&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&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="p"&gt;.....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now within the try block, we need to write the query to insert a row in a table. The query() method lets you denote variable values in the string query as $1, $2 etc. and then provide those variables in order in an array. This will be how we add our variable inputs from user to the query.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INSERT INTO events (title, description, start_time, end_time) VALUES ($1, $2, $3, $4) RETURNING *&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;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end_time&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;ul&gt;
&lt;li&gt;Again, like the previous time, we will print the result rows. But this time, we only need to print the first element of the 'rows' array, which will be the row we just inserted.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// 201 = Resource Created&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Hurray, we've built our endpoint to add new events! Here's the entire code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/events&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end_time&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Destructuring the input data&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Insert the event details into a new row in the table&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INSERT INTO events (title, description, start_time, end_time) VALUES ($1, $2, $3, $4) RETURNING *&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;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end_time&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// 201 = Resource Created&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;e&lt;/span&gt;&lt;span class="p"&gt;)&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="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to create event.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 500 = Internal Server Error&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  GET /event/:id : Fetch details of an individual event
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;I'm sure you are clever enough to be able to set up a basic function for any endpoint, so I will not be showing that every time.&lt;/li&gt;
&lt;li&gt;Here, our goal is to create a dynamic endpoint, where the value of 'id' will keep changing. So, we've marked it as :id, and we can access its value as follows:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can also be done outside the try-catch, just like the input values in the previous endpoint.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now within the try block, we need to write the query for selecting rows where the 'id' field will be equal to the id provided. If there's no results found, that means the event with this id doesn't exist, so we can return a 404 error.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM events WHERE id = $1&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;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&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="c1"&gt;// event not found&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Event not found.&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;ul&gt;
&lt;li&gt;If this isn't the case, that means the event exists. But since 'rows' is an array, so even if it contains one element, we need to access it by rows[0]. So the required row is in rows[0].
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;And voila! You can now successfully get a specific event's details! Here's the full code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/event/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Destructuring the URL parameters&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Get the current event row&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT * FROM events where id = $1&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;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&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="c1"&gt;// length 0 means no rows returned, i.e. event isn't found&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No event found.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 404 = Resource Not Found&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// 200 = OK&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;e&lt;/span&gt;&lt;span class="p"&gt;)&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="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Database error.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 500 = Internal Server Error&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  User Registration
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Supabase
&lt;/h4&gt;

&lt;p&gt;For implementing this feature, you will need to create a new table in Supabase first.&lt;/p&gt;

&lt;p&gt;Go to SQL Editor and run the following query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;registrations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;event_id&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;country&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;specialty&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  POST /event/:id/register
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;We can take the input values as well as the parameter value outside the try-catch.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;specialty&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&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="p"&gt;.....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now we will first check whether the event with 'id' exists. For this, we will follow the approach of GET /event/:id, and check if rows.length is nonzero, i.e. it has some results.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;event&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;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM events WHERE id = $1&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;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Event not found.'});
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now that the event exists, we can write the query for actually adding a registration to the database to the new table we just created, i.e. 'registrations'.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;registration&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;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INSERT INTO registrations (event_id, name, country, specialty) VALUES ($1, $2, $3, $4) RETURNING *&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;specialty&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Registration successful!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Thus we have implemented a feature for registering users for an event as well! Here's the entire code:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/event/:id/register&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Destructuring URL parameters&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dept&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;college&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;laptop&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Destructuring input data&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Checking if event exists&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;event&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;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT * FROM events where id = $1&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;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&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="c1"&gt;// length 0 means no rows returned, i.e. event isn't found&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Event not found.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 404 = Resource Not Found&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Insert new row for new registration&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;registration&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;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INSERT INTO registrations (event_id, name, dept, college, country, laptop) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dept&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;college&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;laptop&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Registration successful!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]});&lt;/span&gt; &lt;span class="c1"&gt;// 201 = Resource Created&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;e&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="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to register for event.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// 500 = Internal Server Error&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  GET /event/:id/registrations : Fetch all registrations for a given event
&lt;/h3&gt;

&lt;p&gt;This one is a homework for you guys. (Don't be mad, if you couldn't do it even after trying, the GitHub code is always available)&lt;br&gt;
A hint: You may check if the event exists in the same way as we did in POST /event/:id/register. After that, you need to write a SELECT query for registrations table to fetch all rows with the given event_id.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Similarly, you may also try and build an endpoint for deleting a particular event, like DELETE /event/:id .&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Congratulations! You have successfully created your own API for scheduling events and managing user registrations. You have come a long way.&lt;/p&gt;

&lt;p&gt;You can add more features, like adding a cron job so that events whose end_time have passed are deleted automatically.&lt;/p&gt;

&lt;p&gt;If you liked this post, drop a like, and comment if you have any doubts or just want to chat related to this. Also follow me on LinkedIn: &lt;a href="https://www.linkedin.com/in/amartya-chowdhury/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/amartya-chowdhury/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>postgres</category>
      <category>sql</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
