<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Software Alchemist]]></title><description><![CDATA[Code, Life, and Debugging the Human Experience.]]></description><link>https://hamidreza.tech</link><generator>RSS for Node</generator><lastBuildDate>Sat, 18 Apr 2026 11:20:54 GMT</lastBuildDate><atom:link href="https://hamidreza.tech/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Javascript's Tricky "This" Keyword and Why Arrow Functions Matter]]></title><description><![CDATA[JavaScript's flexibility and dynamic nature make it a powerful language, but certain feature - like the this keyword - can lead to confusion, especially within nested functions. Understanding how this behaves is crucial for writing predictable and ma...]]></description><link>https://hamidreza.tech/javascripts-this-keyword-and-arrow-functions</link><guid isPermaLink="true">https://hamidreza.tech/javascripts-this-keyword-and-arrow-functions</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Programming Tips]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Hamidreza Mahdavipanah]]></dc:creator><pubDate>Tue, 18 Mar 2025 14:28:41 GMT</pubDate><content:encoded><![CDATA[<p>JavaScript's flexibility and dynamic nature make it a powerful language, but certain feature - like the <code>this</code> keyword - can lead to confusion, especially within nested functions. Understanding how <code>this</code> behaves is crucial for writing predictable and maintainable code.</p>
<h3 id="heading-the-this-keyword-in-javascript">The <code>this</code> Keyword in JavaScript</h3>
<p>In JavaScript, the value of <code>this</code> is determined by how a function is invoked, not where it's defined. When a regular function is called as a method of an object (<code>obj.method()</code>), <code>this</code> refers to that object. However, when a function is invoked standalone (<code>func()</code>), <code>this</code> typically refers to the global object (in non-strict mode) or is <code>undefined</code> (in strict mode) (<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this">MDN documentation</a>).</p>
<h3 id="heading-common-pitfall-losing-the-context">Common Pitfall: Losing the Context</h3>
<p>Consider the following example:</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.factor = <span class="hljs-number">2</span>;
  }

  methodA(value) {
    <span class="hljs-keyword">return</span> value * <span class="hljs-built_in">this</span>.factor;
  }

  methodB() {
    <span class="hljs-keyword">return</span> [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>].map(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">value</span>) </span>{
      <span class="hljs-keyword">const</span> newValue = value + <span class="hljs-number">1</span>;
      <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.methodA(newValue); <span class="hljs-comment">// TypeError: Cannot read properties of undefined (reading 'methodA')</span>
    });
  }
}
</code></pre>
<p>In this example, the callback passed to <code>map()</code> is a regular function, causing <code>this</code> to be <code>undefined</code> inside it. This results in a runtime error.</p>
<h3 id="heading-arrow-functions-a-concise-solution">Arrow Functions: A Concise Solution</h3>
<p>Arrow functions provide a concise syntax and lexically bind <code>this</code>, meaning they inherit <code>this</code> from their surrounding scope (<a target="_blank" href="https://google.github.io/styleguide/jsguide.html#features-functions-arrow-functions">Google JS Style Guide</a>):</p>
<pre><code class="lang-javascript"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.factor = <span class="hljs-number">2</span>;
  }

  methodA(value) {
    <span class="hljs-keyword">return</span> value * <span class="hljs-built_in">this</span>.factor;
  }

  methodB() {
    <span class="hljs-keyword">return</span> [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>].map(<span class="hljs-function">(<span class="hljs-params">value</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> newValue = value + <span class="hljs-number">1</span>;
      <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.methodA(newValue);
    });
  }
}
</code></pre>
<p>With arrow functions, the context of <code>this</code> remains bound to the instance of <code>MyClass</code>, preventing the earlier error.</p>
<h3 id="heading-best-practices">Best Practices</h3>
<p>To avoid confusion and potential errors with <code>this</code>, consider these guidelines:</p>
<ul>
<li><p><strong>Prefer Arrow Functions for Nested Functions:</strong> Arrow functions simplify the scoping of <code>this</code> in nested functions.</p>
</li>
<li><p><strong>Avoid Function Expressions for Callbacks:</strong> Regular functions can lead to unexpected bindings. Use arrow functions for callbacks.</p>
</li>
<li><p><strong>Explicit Binding with</strong> <code>bind</code>: If using regular functions, explicitly bind <code>this</code> using <code>.bind(this)</code> (<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">MDN bind</a>).</p>
</li>
</ul>
<p>By understanding the behavior of <code>this</code> and utilizing arrow functions appropriately, you can write more predictable and maintainable JavaScript code.</p>
]]></content:encoded></item><item><title><![CDATA[Introducing keyv-upstash: Seamless Key-Value Storage for Serverless Redis]]></title><description><![CDATA[Github: https://github.com/mahdavipanah/keyv-upstash
keyv-upstash is a storage adapter for Keyv that connects it to Upstash Redis, a serverless Redis platform. With this adapter, you get a simple, efficient, and flexible solution for key-value storag...]]></description><link>https://hamidreza.tech/introducing-keyv-upstash</link><guid isPermaLink="true">https://hamidreza.tech/introducing-keyv-upstash</guid><category><![CDATA[Redis]]></category><category><![CDATA[caching]]></category><category><![CDATA[serverless]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Databases]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Hamidreza Mahdavipanah]]></dc:creator><pubDate>Tue, 10 Dec 2024 17:27:11 GMT</pubDate><content:encoded><![CDATA[<p>Github: <a target="_blank" href="https://github.com/mahdavipanah/keyv-upstash">https://github.com/mahdavipanah/keyv-upstash</a></p>
<p><code>keyv-upstash</code> is a storage adapter for <a target="_blank" href="https://github.com/jaredwray/keyv">Keyv</a> that connects it to <a target="_blank" href="https://upstash.com/">Upstash Redis</a>, a serverless Redis platform. With this adapter, you get a simple, efficient, and flexible solution for key-value storage in serverless applications.</p>
<h2 id="heading-what-is-keyv">What is Keyv?</h2>
<p>Keyv is a versatile key-value storage library that supports multiple backends through adapters. It provides:</p>
<ul>
<li><p><strong>TTL-based Expiry</strong>: Ideal for caching or persistent storage.</p>
</li>
<li><p><strong>Namespace Support</strong>: Avoids key collisions in shared environments.</p>
</li>
<li><p><strong>Extensibility</strong>: Easy to build custom modules or add features like compression.</p>
</li>
</ul>
<p>Keyv works with many adapters, such as Redis, SQLite, MongoDB, and now, <code>keyv-upstash</code> for Upstash Redis.</p>
<hr />
<h2 id="heading-why-keyv-upstash">Why <code>keyv-upstash</code>?</h2>
<p><code>keyv-upstash</code> extends Keyv's capabilities by integrating it with Upstash Redis, offering:</p>
<ol>
<li><p><strong>Serverless Compatibility</strong>: Upstash Redis works without managing connections, scaling automatically, perfect for serverless apps.</p>
</li>
<li><p><strong>Flexible</strong>: Compatible with Keyv’s ecosystem and supports third-party extensions.</p>
</li>
<li><p><strong>Cache Layering</strong>: Combine with <a target="_blank" href="https://www.npmjs.com/package/cacheable">Cacheable</a> for multi-layered caching.</p>
</li>
<li><p><strong>No Vendor Lock-In:</strong> Is fully compatible with <a target="_blank" href="https://github.com/hiett/serverless-redis-http">serverless-redis-http</a> so you can setup your own serverless Redis and use this adapter with it.</p>
</li>
</ol>
<hr />
<h2 id="heading-getting-started">Getting Started</h2>
<p>Follow these steps to integrate <code>keyv-upstash</code>:</p>
<h3 id="heading-1-install-keyv-and-keyv-upstash">1. Install Keyv and <code>keyv-upstash</code></h3>
<p>Install Keyv and the Upstash adapter:</p>
<pre><code class="lang-bash">npm install keyv keyv-upstash
</code></pre>
<p>Optional: Install Cacheable for layered caching:</p>
<pre><code class="lang-bash">npm install cacheable
</code></pre>
<hr />
<h3 id="heading-2-set-up-keyv-upstash">2. Set Up <code>keyv-upstash</code></h3>
<p>Make sure you have a Redis database created in <a target="_blank" href="https://upstash.com/">Upstash</a>. Here’s how to use <code>keyv-upstash</code> in your project:</p>
<h4 id="heading-basic-usage">Basic Usage</h4>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> Keyv <span class="hljs-keyword">from</span> <span class="hljs-string">'keyv'</span>;
<span class="hljs-keyword">import</span> { KeyvUpstash } <span class="hljs-keyword">from</span> <span class="hljs-string">'keyv-upstash'</span>;

<span class="hljs-keyword">const</span> keyv = <span class="hljs-keyword">new</span> Keyv({
  store: <span class="hljs-keyword">new</span> KeyvUpstash({
    url: <span class="hljs-string">'your-upstash-redis-url'</span>,
    token: <span class="hljs-string">'your-upstash-redis-token'</span>,
  }),
});

<span class="hljs-comment">// Set a key-value pair</span>
<span class="hljs-keyword">await</span> keyv.set(<span class="hljs-string">'foo'</span>, <span class="hljs-string">'bar'</span>);

<span class="hljs-comment">// Retrieve the value</span>
<span class="hljs-keyword">const</span> value = <span class="hljs-keyword">await</span> keyv.get(<span class="hljs-string">'foo'</span>);
<span class="hljs-built_in">console</span>.log(value); <span class="hljs-comment">// 'bar'</span>
</code></pre>
<h4 id="heading-using-namespaces">Using Namespaces</h4>
<p>Namespaces prevent key collisions and allow scoped clearing:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> keyv = <span class="hljs-keyword">new</span> Keyv({
  store: <span class="hljs-keyword">new</span> KeyvUpstash({
    url: <span class="hljs-string">'your-upstash-redis-url'</span>,
    token: <span class="hljs-string">'your-upstash-redis-token'</span>,
    <span class="hljs-keyword">namespace</span>: <span class="hljs-string">'my-namespace'</span>,
  }),
});

<span class="hljs-keyword">await</span> keyv.set(<span class="hljs-string">'foo'</span>, <span class="hljs-string">'bar'</span>); <span class="hljs-comment">// Stored as 'my-namespace::foo'</span>
</code></pre>
<h4 id="heading-cache-layering-with-cacheable">Cache Layering with Cacheable</h4>
<p>Combine <code>keyv-upstash</code> with Cacheable for multi-layer caching:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Cacheable } <span class="hljs-keyword">from</span> <span class="hljs-string">'cacheable'</span>;

<span class="hljs-keyword">const</span> redisStore = <span class="hljs-keyword">new</span> KeyvUpstash({
  url: <span class="hljs-string">'your-upstash-redis-url'</span>,
  token: <span class="hljs-string">'your-upstash-redis-token'</span>,
});

<span class="hljs-keyword">const</span> cache = <span class="hljs-keyword">new</span> Cacheable({
  primary: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>(), <span class="hljs-comment">// Fast in-memory caching</span>
  secondary: redisStore, <span class="hljs-comment">// Persistent Redis caching</span>
});

<span class="hljs-keyword">await</span> cache.set(<span class="hljs-string">'foo'</span>, <span class="hljs-string">'bar'</span>, { ttl: <span class="hljs-number">1000</span> }); <span class="hljs-comment">// Stores in both layers</span>
<span class="hljs-keyword">const</span> value = <span class="hljs-keyword">await</span> cache.get(<span class="hljs-string">'foo'</span>); <span class="hljs-comment">// Fast lookup from memory or Redis</span>
<span class="hljs-built_in">console</span>.log(value); <span class="hljs-comment">// 'bar'</span>
</code></pre>
<hr />
<h2 id="heading-advanced-features">Advanced Features</h2>
<h3 id="heading-batch-operations">Batch Operations</h3>
<p>Improve performance with <code>setMany</code> and <code>getMany</code>:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">await</span> keyv.setMany([
  { key: <span class="hljs-string">'key1'</span>, value: <span class="hljs-string">'value1'</span> },
  { key: <span class="hljs-string">'key2'</span>, value: <span class="hljs-string">'value2'</span> },
]);

<span class="hljs-keyword">const</span> values = <span class="hljs-keyword">await</span> keyv.getMany([<span class="hljs-string">'key1'</span>, <span class="hljs-string">'key2'</span>]);
<span class="hljs-built_in">console</span>.log(values); <span class="hljs-comment">// ['value1', 'value2']</span>
</code></pre>
<h3 id="heading-custom-configuration">Custom Configuration</h3>
<p>Customize your setup with options like <code>defaultTtl</code>, <code>keyPrefixSeparator</code>, and <code>clearBatchSize</code>.</p>
]]></content:encoded></item><item><title><![CDATA[Fast and Simple NestJS App Deployment on Vercel]]></title><description><![CDATA[This guide is beneficial if you're using Express adapter. For NestJS applications utilizing the Fastify adapter, these links may be helpful:

https://fastify.dev/docs/latest/Guides/Serverless/#vercel

https://github.com/vercel/examples/tree/main/star...]]></description><link>https://hamidreza.tech/nestjs-on-vercel</link><guid isPermaLink="true">https://hamidreza.tech/nestjs-on-vercel</guid><category><![CDATA[nestjs]]></category><category><![CDATA[Vercel]]></category><category><![CDATA[deployment]]></category><category><![CDATA[Express]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[Hamidreza Mahdavipanah]]></dc:creator><pubDate>Tue, 26 Nov 2024 19:10:38 GMT</pubDate><content:encoded><![CDATA[<blockquote>
<p>This guide is beneficial if you're using <a target="_blank" href="https://expressjs.com/">Express</a> adapter. For NestJS applications utilizing the <a target="_blank" href="https://fastify.dev/">Fastify</a> adapter, these links may be helpful:</p>
<ul>
<li><p><a target="_blank" href="https://fastify.dev/docs/latest/Guides/Serverless/#vercel">https://fastify.dev/docs/latest/Guides/Serverless/#vercel</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/vercel/examples/tree/main/starter/fastify">https://github.com/vercel/examples/tree/main/starter/fastify</a></p>
</li>
</ul>
</blockquote>
<p>🚀 You can access the complete source code discussed in this article at this GitHub repository: <a target="_blank" href="https://github.com/mahdavipanah/nestjs-on-vercel">https://github.com/mahdavipanah/nestjs-on-vercel</a></p>
<h2 id="heading-vercels-support-for-express-apps">Vercel's Support for Express Apps</h2>
<p>Vercel offers a convenient feature for deploying your Express app by:</p>
<ol>
<li><p>Exposing the Express app object in an API.</p>
</li>
<li><p>Defining a rewrite rule that directs all incoming traffic to this single API.</p>
</li>
</ol>
<p>I followed <a target="_blank" href="https://vercel.com/guides/using-express-with-vercel">Vercel’s official guide for deploying Express</a> to deploy NestJS by similarly exposing NestJS’s underlying Express app object.</p>
<h2 id="heading-step-1-create-a-nestjs-app">Step 1 - create a NestJS app</h2>
<blockquote>
<p>Skip this step if you already have a NestJS app set up.</p>
</blockquote>
<p><a target="_blank" href="https://docs.nestjs.com/first-steps">Install NestJS</a> and create a new app:</p>
<pre><code class="lang-bash">nest new my-app
</code></pre>
<h3 id="heading-step-2-install-necessary-npm-packages"><strong>Step 2 - Install Necessary NPM Packages</strong></h3>
<pre><code class="lang-bash">npm install express @nestjs/platform-express
npm install -D @types/express
</code></pre>
<h2 id="heading-step-3-create-srcappfactoryts-file">Step 3 - Create <code>src/AppFactory.ts</code> file</h2>
<p>This file serves as a single module that manages all necessary NestJS app bootstrapping and exports both the NestJS app and its underlying Express app object.</p>
<p>Create a file named <code>AppFactory.ts</code> inside the <code>src</code> directory in your project’s root:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { ExpressAdapter } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/platform-express'</span>;
<span class="hljs-keyword">import</span> { NestFactory } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/core'</span>;
<span class="hljs-keyword">import</span> express, { Request, Response } <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>;
<span class="hljs-keyword">import</span> { Express } <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>;
<span class="hljs-keyword">import</span> { INestApplication } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { AppModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'./app.module.js'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> AppFactory {
  <span class="hljs-keyword">static</span> create(): {
    appPromise: <span class="hljs-built_in">Promise</span>&lt;INestApplication&lt;<span class="hljs-built_in">any</span>&gt;&gt;;
    expressApp: Express;
  } {
    <span class="hljs-keyword">const</span> expressApp = express();
    <span class="hljs-keyword">const</span> adapter = <span class="hljs-keyword">new</span> ExpressAdapter(expressApp);
    <span class="hljs-keyword">const</span> appPromise = NestFactory.create(AppModule, adapter);

    appPromise
      .then(<span class="hljs-function">(<span class="hljs-params">app</span>) =&gt;</span> {
        <span class="hljs-comment">// You can add all required app configurations here</span>

        <span class="hljs-comment">/**
         * Enable cross-origin resource sharing (CORS) to allow resources to be requested from another domain.
         * @see {@link https://docs.nestjs.com/security/cors}
         */</span>
        app.enableCors({
          exposedHeaders: <span class="hljs-string">'*'</span>,
        });

        app.init();
      })
      .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
        <span class="hljs-keyword">throw</span> err;
      });

    <span class="hljs-comment">// IMPORTANT This express application-level middleware makes sure the NestJS app is fully initialized</span>
    expressApp.use(<span class="hljs-function">(<span class="hljs-params">req: Request, res: Response, next</span>) =&gt;</span> {
      appPromise
        .then(<span class="hljs-keyword">async</span> (app) =&gt; {
          <span class="hljs-keyword">await</span> app.init();
          next();
        })
        .catch(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> next(err));
    });

    <span class="hljs-keyword">return</span> { appPromise, expressApp };
  }
}
</code></pre>
<h2 id="heading-step-4-modify-srcmaints-file"><strong>Step 4 - Modify</strong> <code>src/main.ts</code> File</h2>
<p>By default, NestJS has a <code>src/main.ts</code> file that serves as the entry point of the application, including all configuration and bootstrapping. Modify this file to move everything to the <code>AppFactory.ts</code> file, keeping only the invocation of the <code>listen</code> method:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { AppFactory } <span class="hljs-keyword">from</span> <span class="hljs-string">'./AppFactory.js'</span>;

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bootstrap</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { appPromise } = AppFactory.create();
  <span class="hljs-keyword">const</span> app = <span class="hljs-keyword">await</span> appPromise;

  <span class="hljs-keyword">await</span> app.listen(process.env.PORT ?? <span class="hljs-number">3000</span>);
}
bootstrap();
</code></pre>
<h2 id="heading-step-5-add-apiindexts-file"><strong>Step 5 - Add</strong> <code>api/index.ts</code> File</h2>
<p>By default, the Vercel runtime builds and serves any function created within the <code>/api</code> directory of a project to Vercel (<a target="_blank" href="https://vercel.com/docs/functions/runtimes/node-js">doc</a>). Since Vercel understands and handles the Express app object, create a function inside this directory that exports the Express app object:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/**
 * This file exports Express instance for specifically for the deployment of the app on Vercel.
 */</span>

<span class="hljs-keyword">import</span> { AppFactory } <span class="hljs-keyword">from</span> <span class="hljs-string">'../src/AppFactory.js'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AppFactory.create().expressApp;
</code></pre>
<h2 id="heading-step-6-add-verceljson-file"><strong>Step 6 - Add</strong> <code>vercel.json</code> File</h2>
<p>Create a file named <code>vercel.json</code> in the project’s root directory to configure Vercel. Here, define a rewrite rule for Vercel to use the Express app to serve all incoming traffic (<a target="_blank" href="https://vercel.com/docs/projects/project-configuration">doc</a>).</p>
<p>You can also use a <code>tsconfig.json</code> file at the <code>api</code> directory to configure the Vercel’s TypeScript compiler. Most options are supported aside from <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping"><strong>"Path Mappings"</strong></a> and <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/project-references.html"><strong>"Pr</strong></a><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping"><strong>oject Reference</strong></a><a target="_blank" href="https://www.typescriptlang.org/docs/handbook/project-references.html"><strong>s"</strong></a>.</p>
<pre><code class="lang-typescript">{
  <span class="hljs-string">"version"</span>: <span class="hljs-number">2</span>,
  <span class="hljs-string">"buildCommand"</span>: <span class="hljs-string">"npm run build"</span>,
  <span class="hljs-string">"outputDirectory"</span>: <span class="hljs-string">"."</span>,
  <span class="hljs-string">"rewrites"</span>: [
    {
      <span class="hljs-string">"source"</span>: <span class="hljs-string">"/(.*)"</span>,
      <span class="hljs-string">"destination"</span>: <span class="hljs-string">"/api"</span>
    }
  ]
}
</code></pre>
<h2 id="heading-step-7-create-a-project-on-vercel"><strong>Step 7 - Create a Project on Vercel</strong></h2>
<p>Congratulations 🎉! We are almost done. Now, create a git repository and push your source code to it. Then, go to your Vercel account, create a new project, and import the git repository. You can also use <a target="_blank" href="https://github.com/mahdavipanah/nestjs-on-vercel">this article’s example GitHub repository</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732642786627/ff53c571-d062-486f-9ba0-db195dfb7b93.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Pitfalls of URL and URLSearchParams in JavaScript]]></title><description><![CDATA[It All Started With a Bug
Working with URLs in JavaScript and Node.js should be straightforward, but a recent bug in our project led me down a rabbit hole of subtle quirks in the URL and URLSearchParams APIs. This post will explore these quirks, how ...]]></description><link>https://hamidreza.tech/pitfalls-of-url-and-urlsearchparams-in-nodejs</link><guid isPermaLink="true">https://hamidreza.tech/pitfalls-of-url-and-urlsearchparams-in-nodejs</guid><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[APIs]]></category><category><![CDATA[encoding]]></category><category><![CDATA[debugging]]></category><category><![CDATA[axios]]></category><dc:creator><![CDATA[Hamidreza Mahdavipanah]]></dc:creator><pubDate>Fri, 22 Nov 2024 16:59:48 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-it-all-started-with-a-bug">It All Started With a Bug</h2>
<p>Working with URLs in JavaScript and Node.js should be straightforward, but a recent bug in our project led me down a rabbit hole of subtle quirks in the <a target="_blank" href="https://nodejs.org/api/url.html"><code>URL</code> and <code>URLSearchParams</code> APIs</a>. This post will explore these quirks, how they can cause problems in your code, and what you can do to avoid them.</p>
<hr />
<h2 id="heading-the-problem-url-handling-with-axios">The Problem: URL Handling with Axios</h2>
<p>We encountered this issue while generating URLs and adding hash signatures to them. The query parameters weren’t consistently percent-encoded, leading to unexpected behavior and wrong hash signatures.</p>
<p>It became clear that the interaction between <code>URL</code> and <code>URLSearchParams</code> objects required extra care.</p>
<hr />
<h3 id="heading-pitfall-1-urlsearch-vs-urlsearchparamstostring">Pitfall #1: <code>URL.search</code> vs. <code>URLSearchParams.toString()</code></h3>
<p>The first surprise was the difference between <code>URL.search</code> and <code>URLSearchParams.toString()</code>.</p>
<p>Use care when using <code>.searchParams</code> to modify the <code>URL</code> because, per the <a target="_blank" href="https://url.spec.whatwg.org/">WHATWG specification</a>, the <code>URLSearchParams</code> object uses different rules to determine which characters to percent-encode. For instance, the <code>URL</code> object will not percent-encode the ASCII tilde (<code>~</code>) character, while <code>URLSearchParams</code> will always encode it.</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Example 1</span>
<span class="hljs-keyword">const</span> url = <span class="hljs-keyword">new</span> URL(<span class="hljs-string">"https://example.com?param=foo bar"</span>);
<span class="hljs-built_in">console</span>.log(url.search); <span class="hljs-comment">// prints param=foo%20bar</span>
<span class="hljs-built_in">console</span>.log(url.searchParams.toString()); <span class="hljs-comment">// prints ?param=foo+bar</span>

<span class="hljs-comment">// Example 2</span>
<span class="hljs-keyword">const</span> myURL = <span class="hljs-keyword">new</span> URL(<span class="hljs-string">'https://example.org/abc?foo=~bar'</span>);
<span class="hljs-built_in">console</span>.log(myURL.search);  <span class="hljs-comment">// prints ?foo=~bar</span>
<span class="hljs-comment">// Modify the URL via searchParams...</span>
myURL.searchParams.sort();
<span class="hljs-built_in">console</span>.log(myURL.search);  <span class="hljs-comment">// prints ?foo=%7Ebar</span>
</code></pre>
<p>In our project, we needed to explicitly reassign <code>url.search = url.searchParams.toString()</code> to ensure the query string was encoded consistently.</p>
<hr />
<h3 id="heading-pitfall-2-the-plus-sign-dilemma">Pitfall #2: The Plus Sign Dilemma</h3>
<p>Another gotcha is how <code>URLSearchParams</code> handles <code>+</code> characters. By default, <code>URLSearchParams</code> interprets <code>+</code> as a space, which may lead to data corruption when encoding binary data or Base64 strings.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> params = <span class="hljs-keyword">new</span> URLSearchParams(<span class="hljs-string">"bin=E+AXQB+A"</span>);
<span class="hljs-built_in">console</span>.log(params.get(<span class="hljs-string">"bin"</span>)); <span class="hljs-comment">// "E AXQB A"</span>
</code></pre>
<p>One solution is to use <code>encodeURIComponent</code> before appending values to <code>URLSearchParams</code>:</p>
<pre><code class="lang-typescript">params.append(<span class="hljs-string">"bin"</span>, <span class="hljs-built_in">encodeURIComponent</span>(<span class="hljs-string">"E+AXQB+A"</span>));
</code></pre>
<p>More details are available in the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams#preserving_plus_signs">MDN documentation</a>.</p>
<hr />
<h3 id="heading-pitfall-3-urlsearchparamsget-vs-urlsearchparamstostring">Pitfall #3: <code>URLSearchParams.get</code> vs. <code>URLSearchParams.toString()</code></h3>
<p>Another subtlety arises when comparing the outputs of <code>URLSearchParams.get</code> and <code>URLSearchParams.toString</code>. For example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> params = <span class="hljs-keyword">new</span> URLSearchParams(<span class="hljs-string">"?key=value&amp;key=other"</span>);
<span class="hljs-built_in">console</span>.log(params.get(<span class="hljs-string">"key"</span>)); <span class="hljs-comment">// "value" (first occurrence)</span>
<span class="hljs-built_in">console</span>.log(params.toString()); <span class="hljs-comment">// "key=value&amp;key=other" (all occurrences serialized)</span>
</code></pre>
<p>In multi-valued scenarios, <code>get</code> returns only the first value, while <code>toString</code> serializes all.</p>
<hr />
<h2 id="heading-the-fix-in-our-codebase">The Fix in Our Codebase</h2>
<p>In our project, we resolved the issue by explicitly reassigning the <code>search</code> property:</p>
<pre><code class="lang-typescript">url.search = url.searchParams.toString();
url.searchParams.set(
  <span class="hljs-string">"hash"</span>,
  cryptography.createSha256HmacBase64UrlSafe(url.href, SECRET_KEY ?? <span class="hljs-string">""</span>)
);
</code></pre>
<p>This ensured that all query parameters were properly encoded before adding the <code>hash</code> value.</p>
<hr />
<h2 id="heading-nodejs-querystring-module">Node.js <code>querystring</code> module</h2>
<p>The WHATWG <code>URLSearchParams</code> interface and the <a target="_blank" href="https://nodejs.org/api/querystring.html"><code>querystring</code> module</a> have a similar purpose, but the purpose of the <code>querystring</code> module is more general, as it allows the customization of delimiter characters (<code>&amp;</code> and <code>=</code>). On the other hand, <code>URLSearchParams</code> API is designed purely for URL query strings.</p>
<p><code>querystring</code> is more performant than <code>URLSearchParams</code> but is not a standardized API. Use <code>URLSearchParams</code> when performance is not critical or when compatibility with browser code is desirable.</p>
<p>When using <code>URLSearchParams</code> unlike <code>querystring</code> module, duplicate keys in the form of array values are not allowed. Arrays are stringified using <code>array.toString()</code>, which simply joins all array elements with commas.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> params = <span class="hljs-keyword">new</span> URLSearchParams({
  user: <span class="hljs-string">'abc'</span>,
  query: [<span class="hljs-string">'first'</span>, <span class="hljs-string">'second'</span>],
});
<span class="hljs-built_in">console</span>.log(params.getAll(<span class="hljs-string">'query'</span>));
<span class="hljs-comment">// Prints [ 'first,second' ]</span>
<span class="hljs-built_in">console</span>.log(params.toString());
<span class="hljs-comment">// Prints 'user=abc&amp;query=first%2Csecond'</span>
</code></pre>
<p>With <code>querystring</code> module, the query string <code>'foo=bar&amp;abc=xyz&amp;abc=123'</code> is parsed into:</p>
<pre><code class="lang-typescript">{
  <span class="hljs-string">"foo"</span>: <span class="hljs-string">"bar"</span>,
  <span class="hljs-string">"abc"</span>: [<span class="hljs-string">"xyz"</span>, <span class="hljs-string">"123"</span>]
}
</code></pre>
<hr />
<h2 id="heading-takeaways">Takeaways</h2>
<ol>
<li><p>Be <strong>cautious of how</strong> <code>URLSearchParams</code> handles special characters (e.g. <code>~</code>) and spaces. Use <code>encodeURIComponent</code> when necessary.</p>
</li>
<li><p><strong>Understand the difference between</strong> <code>URL.search</code>, <code>URLSearchParams.get</code>, and <code>URLSearchParams.toString</code> to avoid unexpected behavior.</p>
</li>
<li><p><strong>In Node.js use</strong> <code>querystring</code> <strong>module if</strong> you want to parse duplicate query parameter keys as an array.</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Resolving MongoDB Error When Starting with Homebrew on macOS]]></title><description><![CDATA[Introduction
While installing MongoDB Community Edition on my MacBook using Homebrew (official MongoDB doc), I encountered an issue: the mongodb-community service seemed to start successfully but was listed as error when I checked its status. If you'...]]></description><link>https://hamidreza.tech/mongodb-error-with-homebrew-on-macos</link><guid isPermaLink="true">https://hamidreza.tech/mongodb-error-with-homebrew-on-macos</guid><category><![CDATA[MongoDB]]></category><category><![CDATA[macOS]]></category><category><![CDATA[Homebrew]]></category><category><![CDATA[Databases]]></category><category><![CDATA[troubleshooting]]></category><dc:creator><![CDATA[Hamidreza Mahdavipanah]]></dc:creator><pubDate>Thu, 21 Nov 2024 11:10:55 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>While installing MongoDB Community Edition on my MacBook using Homebrew (<a target="_blank" href="https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-os-x/">official MongoDB doc</a>), I encountered an issue: the <code>mongodb-community</code> service seemed to start successfully but was listed as <strong>error</strong> when I checked its status. If you're facing the same problem, here's a quick guide to help you fix it.</p>
<h2 id="heading-the-issue">The Issue</h2>
<p>After running:</p>
<pre><code class="lang-bash">brew services start mongodb-community
</code></pre>
<p>I received a confirmation message. However, checking the service status with:</p>
<pre><code class="lang-bash">brew services list
</code></pre>
<p>showed:</p>
<pre><code class="lang-bash">Name              Status  User Plist
mongodb-community error
</code></pre>
<p>The MongoDB log (<code>/usr/local/var/log/mongodb/mongo.log</code>) contained warnings:</p>
<ul>
<li><p><strong>Running as root user</strong>: <code>"You are running this process as the root user, which is not recommended"</code></p>
</li>
<li><p><strong>Termination signal received</strong>: <code>"Received signal","attr":{"signal":15,"error":"Terminated: 15"}}</code></p>
</li>
</ul>
<p>These indicated that MongoDB was running as the root user, which can cause permission issues and lead to the service being stopped.</p>
<h2 id="heading-the-solution">The Solution</h2>
<p>The main issue was incorrect ownership of the MongoDB data and log directories. Here's how to fix it:</p>
<h3 id="heading-steps">Steps:</h3>
<ol>
<li><p><strong>Stop the MongoDB Service</strong>:</p>
<pre><code class="lang-bash"> brew services stop mongodb-community
</code></pre>
</li>
<li><p><strong>Terminate Any Running MongoDB Processes</strong>:</p>
<pre><code class="lang-bash"> pkill -f mongod
</code></pre>
</li>
<li><p><strong>Change Ownership of MongoDB Directories</strong>:</p>
<pre><code class="lang-bash"> sudo chown -R $(whoami) /usr/<span class="hljs-built_in">local</span>/var/mongodb
 sudo chown -R $(whoami) /usr/<span class="hljs-built_in">local</span>/var/<span class="hljs-built_in">log</span>/mongodb
</code></pre>
</li>
<li><p><strong>Verify Directory Ownership</strong>:</p>
<pre><code class="lang-bash"> ls -ld /usr/<span class="hljs-built_in">local</span>/var/mongodb
 ls -ld /usr/<span class="hljs-built_in">local</span>/var/<span class="hljs-built_in">log</span>/mongodb
</code></pre>
<p> Ensure your username is listed as the owner.</p>
</li>
<li><p><strong>Start the MongoDB Service as Your User</strong>:</p>
<pre><code class="lang-bash"> brew services start mongodb-community
</code></pre>
</li>
<li><p><strong>Check the Service Status</strong>:</p>
<pre><code class="lang-bash"> brew services list
</code></pre>
<p> The service should now show as <strong>started</strong> under your username.</p>
</li>
<li><p><strong>Test the MongoDB Connection</strong>:</p>
<pre><code class="lang-bash"> mongosh
</code></pre>
<p> You should successfully connect to the MongoDB shell.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>By correcting the directory permissions and ensuring MongoDB runs under your user account (not as root), you can resolve the error when starting the <code>mongodb-community</code> service with Homebrew on macOS. Remember to avoid using <code>sudo</code> with <code>brew</code> commands to prevent permission conflicts.</p>
]]></content:encoded></item><item><title><![CDATA[Using @ and */ symbols inside JS multiline comments]]></title><description><![CDATA[While documenting JavaScript code using JSDoc, I stumbled upon an annoying issue. My attempts to include the /* symbol in the example code within a multiline comment caused the entire comment block to break. This happens because */ is recognized as t...]]></description><link>https://hamidreza.tech/using-special-symbols-inside-js-multiline-comments</link><guid isPermaLink="true">https://hamidreza.tech/using-special-symbols-inside-js-multiline-comments</guid><category><![CDATA[jsdoc]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Hamidreza Mahdavipanah]]></dc:creator><pubDate>Fri, 12 Apr 2024 12:55:37 GMT</pubDate><content:encoded><![CDATA[<p>While documenting JavaScript code using JSDoc, I stumbled upon an annoying issue. My attempts to include the <code>/*</code> symbol in the example code within a multiline comment caused the entire comment block to break. This happens because <code>*/</code> is recognized as the ending tag for a multiline comment in JavaScript.</p>
<p>You can see the problem clearly in the blow code block!</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/**
 * Checks whether two permission strings are semantically equal or not.
 *
 * @example
 * // returns true
 * equals('a/b/c/d/allow', 'a/b/c/*⁣/*/</span>d/allow<span class="hljs-string">');
 *
 * @returns {boolean} True in case of equality and false otherwise.
*/
const equals = (first: string, second: string) =&gt; {
    // function'</span>s logic
    <span class="hljs-comment">// ...</span>

    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; <span class="hljs-comment">// or false</span>
}
</code></pre>
<p>The solution is surprisingly simple: insert a Unicode invisible separator character between <code>*</code> and <code>/</code>. This character acts as a stealthy spacer, preventing the JavaScript interpreter from recognizing the sequence as the end of a comment. You can find and copy this invisible character <a target="_blank" href="https://unicode-explorer.com/c/2063"><strong>here</strong></a>.</p>
<p>The same problem happens if you use the <code>@</code> symbol to put a JSDoc code example of a decorator. Because the <code>@</code> symbol has a special meaning for JSDoc, it leads to unintended changes in the rendered documentation. Consider this snippet:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">/**
 * A NestJS handler decorator that defines an access permission constraint and enforces it.
 *
 * @example
 * `⁣`⁣`ts
 * // the request only needs to be authenticated and doesn't need any specific permissions
 * @RequiresAccess()
 * Class MyController {}
 * `⁣`⁣`
*/</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> RequiresAccess = Reflector.createDecorator&lt;
  PermissionPathGen | PermissionPathGen[]
&gt;({
  transform(value) {
    <span class="hljs-keyword">return</span> value == <span class="hljs-literal">undefined</span> ? MUST_BE_AUTHENTICATED : value;
  },
});
</code></pre>
<p>Solving this is the same as the previous problem, you need to put an <a target="_blank" href="https://unicode-explorer.com/c/2063">invisible separator</a> before the <code>@</code>.</p>
]]></content:encoded></item></channel></rss>