<?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>Forem: Amir Hossein Shekari</title>
    <description>The latest articles on Forem by Amir Hossein Shekari (@vanenshi).</description>
    <link>https://forem.com/vanenshi</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%2F396441%2Ff0f3c1cc-4113-4940-9954-5c600c062f6c.jpeg</url>
      <title>Forem: Amir Hossein Shekari</title>
      <link>https://forem.com/vanenshi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/vanenshi"/>
    <language>en</language>
    <item>
      <title>Why I Ditched SQS for Step Functions (and Ended Up Contributing to SST)</title>
      <dc:creator>Amir Hossein Shekari</dc:creator>
      <pubDate>Mon, 11 May 2026 15:31:26 +0000</pubDate>
      <link>https://forem.com/vanenshi/scaling-the-inbox-how-i-contributed-the-step-functions-construct-to-sst-3ccp</link>
      <guid>https://forem.com/vanenshi/scaling-the-inbox-how-i-contributed-the-step-functions-construct-to-sst-3ccp</guid>
      <description>&lt;p&gt;Every developer knows the "happy path"—that glorious moment when your code works perfectly on a small sample size. But when the "happy path" meets the reality of 100,000+ emails and strict API rate limits, things tend to break.&lt;/p&gt;

&lt;p&gt;This is the story of how a bottleneck in my AI startup, Glim, led me to build and contribute the Step Functions component to the SST (Serverless Stack) ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: The Gmail "Wall"
&lt;/h2&gt;

&lt;p&gt;I was building &lt;strong&gt;Glim&lt;/strong&gt;, an AI assistant designed to help users manage their chaos-ridden inboxes. We offered real-time filtering and a powerful bulk-cleanup tool that could archive or delete thousands of emails based on specific criteria like sender, date, or domain.&lt;/p&gt;

&lt;p&gt;To make this work, I had to implement a &lt;a href="https://developers.google.com/workspace/gmail/api/guides/sync" rel="noopener noreferrer"&gt;full inbox sync&lt;/a&gt;. According to the Google API documentation, this is a two-step process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch a list of all email IDs.&lt;/li&gt;
&lt;li&gt;Iterate through that list and perform a &lt;code&gt;messages.get&lt;/code&gt; request for each individual email's full data.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Math of the 429
&lt;/h3&gt;

&lt;p&gt;Google’s rate limits are notoriously strict and follow a specific &lt;a href="https://developers.google.com/workspace/gmail/api/reference/quota" rel="noopener noreferrer"&gt;quota system&lt;/a&gt;. The limit consists of two primary factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Per-second Unit Limit:&lt;/strong&gt; You are allowed 100 quota units per second.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request Weight:&lt;/strong&gt; Each type of request has a "weight." A &lt;code&gt;messages.get&lt;/code&gt; request costs &lt;strong&gt;20 units&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means you can only fetch &lt;strong&gt;5 emails per second&lt;/strong&gt; (or roughly 300 per minute). If you violate this, Google hits you with a &lt;strong&gt;429 Too Many Requests&lt;/strong&gt; error and an exponential block that gets longer every time you retry too early.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempt One: A SQS Disaster
&lt;/h2&gt;

&lt;p&gt;My first architecture was a classic serverless pattern: &lt;strong&gt;Lambda + SQS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I bundled 20 email IDs into each SQS message. To respect the rate limits, I throttled the message publishing to one message per second. I set a 60-second visibility timeout, figuring that if a batch hit a 429, SQS would simply retry it a minute later based on standard AWS rules.&lt;/p&gt;

&lt;p&gt;It worked... until it didn't.&lt;/p&gt;

&lt;p&gt;For users with fewer than 40,000 emails, it was fine. But for power users with massive inboxes, the math fell apart. Multiple SQS batches would hit the rate limit simultaneously. The 60-second window wasn't long enough to clear the Google block, leading to more retries, more 429s, and a cascading failure that increased the block time exponentially. I realized I didn't just need a queue; I needed a &lt;strong&gt;State Machine&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: The "Scatter-Gather" Step Function
&lt;/h2&gt;

&lt;p&gt;I needed a way to strictly control the flow of execution. If "Batch 1" hit a rate limit, the entire process needed to pause until that block cleared before "Batch 2" even started.&lt;/p&gt;

&lt;p&gt;I decided to move to a &lt;strong&gt;Scatter-Gather&lt;/strong&gt; pattern using AWS Step Functions. This allowed me to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fetch IDs:&lt;/strong&gt; Fetch 500 IDs at a time (even fetching the IDs can hit limits once you pass 40k emails).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strict Flow Control:&lt;/strong&gt; Process the batch, respect the rate limit, then move to the next 500.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Software-Level Backoff:&lt;/strong&gt; Implement an exponential wait step within the flow so that retries don't stack on top of each other at the API gateway level.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Hurdle: SST Didn't Speak Step Functions
&lt;/h2&gt;

&lt;p&gt;At the time, Glim was built entirely on &lt;strong&gt;SST (Serverless Stack)&lt;/strong&gt;. I loved the developer experience of SST, but there was a major missing piece: &lt;strong&gt;it didn't have a built-in component for Step Functions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I had two choices: manually write raw Pulumi code (which would feel out of place in my clean SST codebase) or build a native SST component myself.&lt;/p&gt;

&lt;p&gt;I chose the latter. I designed the component using a &lt;strong&gt;linked-node architecture&lt;/strong&gt;. I visualized the state machine as a circular tree where each node connects the steps of the SF. I wrote the logic to compile this tree into the exact JSON format required for Pulumi (the backend of SST) and pushed it to AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Giving Back to the Community
&lt;/h2&gt;

&lt;p&gt;Once I had a working version, I didn't want to keep it in a silo. I forked the SST repository, integrated my new &lt;code&gt;StepFunctions&lt;/code&gt; component, and used it to successfully fix the Glim inbox sync. It handled 100,000+ emails without breaking a sweat.&lt;/p&gt;

&lt;p&gt;Seeing it work in production, I opened a &lt;a href="https://github.com/anomalyco/sst/pull/5691" rel="noopener noreferrer"&gt;Pull Request&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After several rounds of refinement, the code was merged. Today, that component, born out of a desperate need to sync 100,000 emails without hitting a Google rate limit, is available for everyone in the SST ecosystem to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Queues aren't Orchestrators:&lt;/strong&gt; SQS is great for decoupling, but when you need to "stop the world" to wait for a rate limit, Step Functions are superior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understand the Quota:&lt;/strong&gt; If I hadn't dug into the 20-unit weight of a &lt;code&gt;messages.get&lt;/code&gt; request, I would have kept guessing why my Lambda was failing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scratch your own itch:&lt;/strong&gt; The best open-source contributions come from solving real-world production problems.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, whether you're syncing a massive inbox or orchestrating a complex AI pipeline, you can do it natively within SST. Happy coding!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>sst</category>
    </item>
    <item>
      <title>Boosting VS Code Productivity - Custom Labels for React Component Files</title>
      <dc:creator>Amir Hossein Shekari</dc:creator>
      <pubDate>Fri, 05 Jul 2024 11:33:48 +0000</pubDate>
      <link>https://forem.com/vanenshi/boosting-vs-code-productivity-custom-labels-for-react-component-files-4c47</link>
      <guid>https://forem.com/vanenshi/boosting-vs-code-productivity-custom-labels-for-react-component-files-4c47</guid>
      <description>&lt;p&gt;Ever felt like you're drowning in a sea of &lt;code&gt;index.ts&lt;/code&gt; files? Trust me, I've been there. Working on a massive React project, I found myself constantly lost in a maze of identical-looking files. But then I stumbled upon a game-changer: VS Code's custom labels feature. Let me tell you how it transformed my coding life.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with &lt;code&gt;index.ts&lt;/code&gt; Overload
&lt;/h2&gt;

&lt;p&gt;Picture this: You're deep in the zone, juggling multiple components, when suddenly you need to find that one specific &lt;code&gt;index.ts&lt;/code&gt; file. You open the search bar, and bam! A flood of indistinguishable results. Frustrating, right? That's exactly where I was until I discovered the magic of custom labels.&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%2Fyyctlubc5tvy1g11jvll.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%2Fyyctlubc5tvy1g11jvll.png" alt=" " width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Custom Labels
&lt;/h2&gt;

&lt;p&gt;So, what's the deal with these custom labels? In a nutshell, they're VS Code's way of letting you personalize how file names appear in your editor tabs and search bar. For us React devs drowning in &lt;code&gt;index.ts&lt;/code&gt; files, it's like throwing us a lifeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Custom Labels Step by Step
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Enable Custom Labels
&lt;/h3&gt;

&lt;p&gt;First, you'll need to enable custom labels in your VS Code settings. Just add this line to your settings.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"workbench.editor.customLabels.enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Define Patterns for &lt;code&gt;index.ts&lt;/code&gt; Files
&lt;/h3&gt;

&lt;p&gt;Now, here's where the real magic happens. Add this bit to tell VS Code to replace those generic &lt;code&gt;index.ts&lt;/code&gt; names with their parent directory names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"workbench.editor.customLabels.patterns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"**/index.{ts,js,tsx,jsx}"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${dirname}"&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;
  
  
  3. Customize for Specific Directories
&lt;/h3&gt;

&lt;p&gt;If you're like me and have a specific folder where all your components live, you can target just that directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"workbench.editor.customLabels.patterns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"components/*/index.{ts,js,tsx,jsx}"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${dirname}"&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;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%2Fhfdek4anx3chhiib5xqh.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%2Fhfdek4anx3chhiib5xqh.png" alt=" " width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Benefits of Custom Labels
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increased Readability&lt;/strong&gt;: Instead of a sea of &lt;code&gt;index.tsx&lt;/code&gt; tabs, you'll see "Button", "Header", and so on. It's like your editor suddenly learned to speak your language!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Efficient Searching&lt;/strong&gt;: Searching for specific components became a breeze.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduced Mental Load&lt;/strong&gt;: No more second-guessing which &lt;code&gt;index.ts&lt;/code&gt; I was looking at.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, fellow coders, if you're tired of playing "Where's Waldo?" with your &lt;code&gt;index.ts&lt;/code&gt; files, give custom labels a shot. It's a small change that packs a big punch in your daily coding life. Trust me, your future self will thank you!&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>productivity</category>
      <category>react</category>
    </item>
    <item>
      <title>Building Safe and Dynamic URLs with TypeScript</title>
      <dc:creator>Amir Hossein Shekari</dc:creator>
      <pubDate>Fri, 13 Oct 2023 19:58:13 +0000</pubDate>
      <link>https://forem.com/vanenshi/crafting-dynamic-urls-with-typescript-2li</link>
      <guid>https://forem.com/vanenshi/crafting-dynamic-urls-with-typescript-2li</guid>
      <description>&lt;p&gt;When developing applications, one of the common tasks is constructing URLs, especially when they contain dynamic parts, like IDs. Ensuring the correctness of these URLs can be tedious, leading to potential runtime errors if not done right. This is where TypeScript can lend a hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Need for urlConverter
&lt;/h2&gt;

&lt;p&gt;Using string-based routes can be error-prone. Miss a single character or forget to replace a dynamic segment, and the whole URL can break. By using TypeScript, we can create a utility that helps in generating these URLs while ensuring their correctness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the urlConverter Step by Step
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Organizing URLs
&lt;/h3&gt;

&lt;p&gt;One of the first steps is to have all URLs organized in one place. Enums in TypeScript provide an excellent way to do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;UserUrls&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;getUserUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users/[userId]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;getMyUserURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/users/me&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="c1"&gt;// other URLs can go here...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Extracting Dynamic Parameters
&lt;/h3&gt;

&lt;p&gt;For URLs with dynamic parts, we need a way to recognize and replace them. A custom TypeScript type can help identify these parts:&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;IsParameter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Part&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Part&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="s2"&gt;`[&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;ParamName&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="nx"&gt;ParamName&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FilteredParts&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Path&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;PartA&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="nx"&gt;infer&lt;/span&gt; &lt;span class="nx"&gt;PartB&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="nx"&gt;IsParameter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PartA&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;FilteredParts&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PartB&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;IsParameter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="cm"&gt;/**
 * A very special type that parse a template string to it's object
 * source: https://lihautan.com/extract-parameters-type-from-string-literal-types-with-typescript/
 * type ParamObject = Params&amp;lt;'/purchase/[shopId]/[itemId]'&amp;gt;;
 * type ParamObject = {
 *      shopId: string;
 *      itemId: string;
 *    }
 */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Params&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Key&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;FilteredParts&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This type works to find any segment enclosed within [].&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Confirming the Presence of Parameters
&lt;/h3&gt;

&lt;p&gt;To ensure that if a URL requires parameters, they're provided, we can use another 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;HasParams&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Path&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Path&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;[&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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="kc"&gt;false&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 check if a route needs parameters.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Creating the urlConverter Function
&lt;/h3&gt;

&lt;p&gt;With all the above in place, we can now create our utility:&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;AllEnums&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;UserUrls&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;urlConverter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;AllEnums&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;routeKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;paramsArr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HasParams&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;routeKey&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Params&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;routeKey&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&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;Invalid route key&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;paramsArr&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&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="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;paramKey&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="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;paramKey&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&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="nx"&gt;paramKey&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="nx"&gt;value&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;return&lt;/span&gt; &lt;span class="nx"&gt;route&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;h2&gt;
  
  
  Usage Example
&lt;/h2&gt;

&lt;p&gt;Generating a reset URL with a given token can be done easily:&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;const&lt;/span&gt; &lt;span class="nx"&gt;getUserUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;urlConverter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;UserUrls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getUserUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="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="nx"&gt;getUserUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Outputs: `/users/12`&lt;/span&gt;

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

&lt;/div&gt;



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

&lt;p&gt;The &lt;code&gt;urlConverter&lt;/code&gt; utility ensures that constructing dynamic URLs is straightforward and less error-prone. Leveraging TypeScript allows for catching potential mistakes at compile-time rather than runtime, resulting in more robust applications.&lt;/p&gt;




&lt;p&gt;I hope this approach helps in your development journey, ensuring cleaner and safer URL generation with TypeScript.&lt;/p&gt;

</description>
      <category>typescript</category>
    </item>
    <item>
      <title>Protect Production Database from Wrong Migrations</title>
      <dc:creator>Amir Hossein Shekari</dc:creator>
      <pubDate>Tue, 25 Apr 2023 15:03:58 +0000</pubDate>
      <link>https://forem.com/vanenshi/how-i-saved-my-production-database-with-one-simple-console-message-4fjm</link>
      <guid>https://forem.com/vanenshi/how-i-saved-my-production-database-with-one-simple-console-message-4fjm</guid>
      <description>&lt;p&gt;As a .NET developer, I had a close call when I applied a migration to my production database without changing the database connection string. I was mortified when I realized my mistake, but I quickly got to work finding a solution to prevent it from happening again.&lt;/p&gt;

&lt;p&gt;That's when I came up with the idea to add a console message that displays the migration details before applying it. This simple addition gives me the chance to review the migration details and ensure that I am working with the correct database before making any changes.&lt;/p&gt;

&lt;p&gt;With this new safeguard in place, I can breathe easy knowing that my production database is safe from accidental alterations. It just goes to show that sometimes the simplest solutions can be the most effective.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApplicationDbContextFactory&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDesignTimeDbContextFactory&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ApplicationDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ApplicationDbContext&lt;/span&gt; &lt;span class="nf"&gt;CreateDbContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// ... Some code to generate dbContextBuilder&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ApplicationDbContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dbContextBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// This is where magic happends&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pendingMigrations&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetPendingMigrations&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"*********************************************\n"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"This command is going to apply migrations with following details"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ConnectionString: "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForegroundColor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConsoleColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Yellow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetColor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Migrations:\n\t"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForegroundColor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConsoleColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Yellow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n\t"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pendingMigrations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToArray&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetColor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"*********************************************"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Do You confirm? (Y/N)"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;userInput&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadLine&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="n"&gt;userInput&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="s"&gt;"Y"&lt;/span&gt; &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="s"&gt;"y"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ForegroundColor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConsoleColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Red&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Aborted!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;More info about the &lt;a href="https://learn.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=dotnet-core-cli" rel="noopener noreferrer"&gt;&lt;code&gt;ApplicationDbContextFactory&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnet</category>
      <category>database</category>
    </item>
    <item>
      <title>Toggle your VPN connection with a shortcut, in Manjaro</title>
      <dc:creator>Amir Hossein Shekari</dc:creator>
      <pubDate>Mon, 31 May 2021 15:55:55 +0000</pubDate>
      <link>https://forem.com/vanenshi/toggle-your-vpn-connection-with-a-shortcut-in-manjaro-10ie</link>
      <guid>https://forem.com/vanenshi/toggle-your-vpn-connection-with-a-shortcut-in-manjaro-10ie</guid>
      <description>&lt;p&gt;This is a little script that allows you to toggle your VPN connection by running a bash script. &lt;br&gt;
I mostly use it by assigning it to a shortcut (meta + v).&lt;/p&gt;


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


</description>
      <category>linux</category>
      <category>arch</category>
      <category>bash</category>
      <category>manjaro</category>
    </item>
  </channel>
</rss>
