<?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: João Textor</title>
    <description>The latest articles on DEV Community by João Textor (@joaotextor).</description>
    <link>https://dev.to/joaotextor</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%2F1159539%2F36656d49-0d34-4291-a272-2749189494f6.png</url>
      <title>DEV Community: João Textor</title>
      <link>https://dev.to/joaotextor</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joaotextor"/>
    <language>en</language>
    <item>
      <title>The Gamification of Coding</title>
      <dc:creator>João Textor</dc:creator>
      <pubDate>Mon, 01 Jan 2024 19:00:00 +0000</pubDate>
      <link>https://dev.to/joaotextor/the-gamification-of-coding-5fmm</link>
      <guid>https://dev.to/joaotextor/the-gamification-of-coding-5fmm</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TL;DR&lt;/li&gt;
&lt;li&gt;The Revolution of Gamification in Coding Learning&lt;/li&gt;
&lt;li&gt;Dopamine's Role in Coding Engagement&lt;/li&gt;
&lt;li&gt;Psychological Rewards of Error Resolution and Successful Tests&lt;/li&gt;
&lt;li&gt;Impact of Visual Feedback on Programmer's Motivation&lt;/li&gt;
&lt;li&gt;Organizational Tools: Kanban Boards and Story Points&lt;/li&gt;
&lt;li&gt;Linking Gamification, Dopamine Release, and Skill Development&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TL;DR&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This blog post explores how gamification transforms coding into an engaging and enjoyable experience. It highlights the role of dopamine in boosting motivation, the satisfaction from solving coding errors, the impact of visual feedback on productivity, and the effectiveness of organizational tools like Kanban boards. The post concludes by examining how gamification and dopamine release aid in developing coding skills, making the learning process more effective and fun.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;The Revolution of Gamification in Coding Learning
&lt;/h2&gt;

&lt;p&gt;Gamification in coding has revolutionized the way I approach learning and developing programming skills. By incorporating game-like elements into coding, the process becomes more engaging and fun, transforming a sometimes monotonous task into an exciting adventure. This method capitalizes on our brain's response to rewards and achievements, making each step in learning to code feel like a level in a game. I find that this approach keeps me motivated and eager to tackle more complex coding challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Dopamine's Role in Coding Engagement
&lt;/h2&gt;

&lt;p&gt;Dopamine, a neurotransmitter associated with feelings of pleasure and motivation, plays a crucial role in the gamification of coding. When I solve a coding problem or understand a new concept, my brain releases dopamine, which not only makes me feel good but also enhances my motivation to continue learning. This biochemical response is a powerful motivator, keeping me engaged and focused on my coding tasks for longer periods.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Psychological Rewards of Error Resolution and Successful Tests
&lt;/h2&gt;

&lt;p&gt;The psychological rewards of coding are not to be underestimated. Every time I see errors disappear from my code or watch my tests turn green, it feels like a mini-victory. This sense of achievement is profoundly satisfying and encourages me to keep refining and improving my code. The immediate feedback loop in coding, where I can see the results of my work in real-time, provides a continuous source of motivation and satisfaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Impact of Visual Feedback on Programmer's Motivation
&lt;/h2&gt;

&lt;p&gt;Visual feedback in coding, such as the disappearing red underlined code, significantly impacts my motivation and productivity. The visual cues act as instant gratification for the work I put in. It's not just about the code working correctly; it's about seeing that visual confirmation that something has been fixed or achieved. This kind of feedback keeps me motivated to maintain high-quality code and strive for fewer errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Organizational Tools: Kanban Boards and Story Points
&lt;/h2&gt;

&lt;p&gt;Implementing "to-do lists," similar to Kanban boards, and utilizing story points have been game-changers in how I organize and motivate myself in coding projects. These tools allow me to break down tasks into manageable chunks, making my goals seem more achievable. The satisfaction of moving a task from 'to-do' to 'done' is similar to completing a level in a game, providing a clear sense of progress and accomplishment.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;Linking Gamification, Dopamine Release, and Skill Development
&lt;/h2&gt;

&lt;p&gt;The relationship between gamification, dopamine release, and the development of coding skills is a fascinating aspect of learning to code. The gamified elements in coding act as a catalyst for dopamine release, which not only makes the learning process more enjoyable but also enhances memory retention and skill development. As I engage with these gamified aspects, I notice a significant improvement in my coding abilities, as well as an increase in my overall enthusiasm for coding.&lt;/p&gt;

&lt;p&gt;Happy 2024 for all of you, and happy coding.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>learning</category>
      <category>programming</category>
      <category>gamification</category>
    </item>
    <item>
      <title>A Beginner Developer 2023 Recap</title>
      <dc:creator>João Textor</dc:creator>
      <pubDate>Sun, 31 Dec 2023 14:26:03 +0000</pubDate>
      <link>https://dev.to/joaotextor/a-beginner-developer-yearly-recap-iml</link>
      <guid>https://dev.to/joaotextor/a-beginner-developer-yearly-recap-iml</guid>
      <description>&lt;p&gt;Looking back, 2023 was the year my brain did more code crunches than I did at the gym (which, by the way, were few). This was the year I decided to dive headfirst into a career transition to programming - not that I was running away from my current job, but let's just say that developing software and bringing projects to life makes my heart beat faster.&lt;/p&gt;

&lt;p&gt;In my current job, which has as much to do with software development as a duck has to do with classical ballet, I ended up creating 5 tools to make everyone's life easier (including mine). I think I ended up being more useful than I expected!&lt;/p&gt;

&lt;p&gt;Personally, I lost count of how many projects I started. I finished some, others... well, let's just say they are in a "creative pause". I completed a Full Stack JavaScript course and a postgraduate in multi-platform mobile development that I started in 2022, and I did a bunch of other courses on Udemy. Let's just say my brain was on a learning marathon.&lt;/p&gt;

&lt;p&gt;I used AI assistants in programming less than I expected. They are good for shaking off the rust or writing that basic code, but at the peak of programming "flow", these assistants are like someone trying to help cook and just making a mess. Useful, but sometimes they hinder more than they help. It's like giving a recipe book to a chef while he's preparing dinner! 🤖💻👨‍🍳&lt;/p&gt;

&lt;p&gt;I learned some cool things that I will take to all my future projects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;TypeScript: at first, I thought it was just a "gourmet" version of JavaScript. But now, without it, I feel like I'm trying to navigate without GPS. Lost, confused, and always searching for that guidance beacon that TypeScript offers.&lt;/li&gt;
&lt;li&gt;Clean Architecture: it was like those gourmet recipes you see on TV and think "I'm never going to make that". But, surprise! I ended up adopting it in my project, like someone who starts making artisanal burgers at home. Unexpected, a bit challenging, but incredibly satisfying for the organization it provides.&lt;/li&gt;
&lt;li&gt;Unit and integration testing: before, I saw them as a tedious task. Now, I realize they are more crucial than I thought. If I applied the same dedication to testing my social life as I do with my code, maybe I wouldn't just be great at the keyboard, but also a master of casual conversation. Imagine that, implementing TDD (Test Driven Dating) to improve my social skills! 😄👨‍💻🎉&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And, by chance, I entered the open-source world with a project for the abstraction of the DataJud API, from CNJ. It became more popular than I expected (check it out: &lt;a href="https://github.com/joaotextor/busca-processos-judiciais"&gt;https://github.com/joaotextor/busca-processos-judiciais&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Now I'm working on a personal SaaS project and thinking about another one. They certainly won't make me the next Bill Gates, but the learning is worth every second.&lt;/p&gt;

&lt;p&gt;Finally, here's my GitHub retrospective. I hope next year's numbers are even more impressive!&lt;/p&gt;

&lt;p&gt;A happy new year to everyone, with lots of health and dreams fulfilled (and, of course, lots of code)!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/EVEOCo417FI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>recap</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>What I Love in TypeScript</title>
      <dc:creator>João Textor</dc:creator>
      <pubDate>Thu, 28 Dec 2023 19:27:35 +0000</pubDate>
      <link>https://dev.to/joaotextor/what-i-love-in-typescript-5dci</link>
      <guid>https://dev.to/joaotextor/what-i-love-in-typescript-5dci</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Reasons to Migrate to TypeScript:
&lt;/h3&gt;

&lt;p&gt;Enhances code quality and readability with its strict typing system.&lt;br&gt;
Improves collaboration and maintainability in team environments.&lt;br&gt;
Offers superior tooling and ecosystem with robust IDE integration and developer tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Top 3 TypeScript Features:
&lt;/h3&gt;

&lt;p&gt;Static Typing: Ensures higher code reliability and reduces runtime errors.&lt;br&gt;
Advanced OOP Features: Supports interfaces, generics, decorators for more scalable code.&lt;br&gt;
Seamless JavaScript Integration: Allows incremental adoption and leverages JavaScript familiarity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learning TypeScript: Strategies for Beginners:
&lt;/h3&gt;

&lt;p&gt;Start with small integrations into existing JavaScript projects.&lt;br&gt;
Utilize TypeScript documentation extensively.&lt;br&gt;
Engage with the TypeScript community for support and learning.&lt;br&gt;
Practice regularly to gain fluency.&lt;br&gt;
Be patient and persistent in the learning process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Typescript has become a game-changer in the world of web development. As someone who has navigated the transition from JavaScript to TypeScript, I've come to appreciate its unique features and capabilities. In this article, I'll delve into why migrating from JavaScript to TypeScript can be a transformative step for developers, highlight three standout features that make TypeScript superior to JavaScript, and offer guidance for those finding the learning curve challenging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Migrate from JavaScript to TypeScript?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Enhanced Code Quality and Readability
&lt;/h3&gt;

&lt;p&gt;Typescript brings a layer of clarity and structure to your codebase. With its strict typing system, you can define what type of data each variable or function should handle. This makes the code more predictable and less prone to runtime errors. Unlike JavaScript, where debugging can often be a game of guesswork, TypeScript’s compile-time error checking flags issues before they become problematic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Improved Collaboration and Maintainability
&lt;/h3&gt;

&lt;p&gt;In team environments, TypeScript’s explicit typing system is a boon. It makes the intentions behind code more apparent, easing the onboarding of new team members and aiding collaboration. Over time, this leads to a codebase that is easier to maintain and evolve, as developers can quickly understand and build upon each other's work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Superior Tooling and Ecosystem
&lt;/h3&gt;

&lt;p&gt;The tooling support for TypeScript is robust, thanks to its integration with popular IDEs and build tools. Features like autocompletion, interface checking, and refactoring tools are incredibly powerful, making the developer's job not just easier but more enjoyable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Top 3 Features Making TypeScript Superior to JavaScript
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Static Typing
&lt;/h3&gt;

&lt;p&gt;The heart of TypeScript’s superiority lies in its static typing system. By enabling developers to define types for variables, functions, and objects, TypeScript ensures a higher level of code reliability and predictability. This drastically reduces runtime errors and improves the quality of the codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Advanced Object-Oriented Programming (OOP) Features
&lt;/h3&gt;

&lt;p&gt;TypeScript embraces OOP more fully than JavaScript. Features like interfaces, generics, and decorators provide a level of functionality and flexibility that JavaScript simply can’t match. These OOP features allow for more reusable, scalable, and modular code, fitting perfectly with modern software design principles.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Seamless Integration with JavaScript
&lt;/h3&gt;

&lt;p&gt;TypeScript doesn’t reinvent the wheel; it enhances it. It’s a superset of JavaScript, meaning any valid JavaScript code is also valid TypeScript. This makes the transition smoother for JavaScript developers and allows for incremental adoption, blending the familiarity of JavaScript with the robustness of TypeScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Struggling to Learn TypeScript? Here’s What to Do
&lt;/h2&gt;

&lt;p&gt;Learning TypeScript can be daunting, especially if you’re coming from a dynamically typed language like JavaScript. However, the following strategies can make the journey easier:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start Small&lt;/strong&gt;: Begin by integrating TypeScript into small parts of your existing JavaScript projects. This gradual approach helps you learn TypeScript in a practical context without being overwhelmed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Embrace the TypeScript Documentation&lt;/strong&gt;: The TypeScript documentation is a treasure trove of information. Spend time with it, and don’t hesitate to refer back to it when you encounter something new or challenging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build a Support&lt;/strong&gt; Network: Engage with the TypeScript community. Platforms like Stack Overflow, GitHub, and TypeScript’s official community channels are great places to seek advice, share experiences, and learn from others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practice Regularly&lt;/strong&gt;: Like any language, fluency in TypeScript comes with practice. Set aside regular time to code in TypeScript, experimenting with its features and understanding its nuances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stay Patient and Persistent&lt;/strong&gt;: Remember, mastering TypeScript is a journey. Celebrate small victories and don’t get discouraged by setbacks.&lt;/p&gt;

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

&lt;p&gt;TypeScript offers a robust, scalable, and more reliable alternative to JavaScript. Its features like static typing, advanced OOP capabilities, and seamless JavaScript integration make it a superior choice for modern web development. For those new to TypeScript, patience, practice, and engagement with the community are key to overcoming the learning curve. Embrace the change, and you’ll soon find TypeScript an indispensable part of your development toolkit.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Abstraindo a API Pública do CNJ - DataJud</title>
      <dc:creator>João Textor</dc:creator>
      <pubDate>Sun, 22 Oct 2023 13:43:07 +0000</pubDate>
      <link>https://dev.to/joaotextor/abstraindo-a-api-publica-do-cnj-datajud-54d</link>
      <guid>https://dev.to/joaotextor/abstraindo-a-api-publica-do-cnj-datajud-54d</guid>
      <description>&lt;p&gt;Nesta semana o Filipe Deschamps postou em sua newsletter oficial sobre a API Pública do DataJud, lançada pelo CNJ para oferecer de forma unificada em uma única API os metadados dos processos judiciais de todo o Brasil (exceto os que tramitam em segredo de justiça).&lt;/p&gt;

&lt;p&gt;Como trabalho atualmente no Judiciário Federal e me interesso por esse assunto, criei uma biblioteca javascript para abstrair o uso dessa API e estou convidando a comunidade open-source brasileira para ajudar na manutenção e construção de novas features😍.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/joaotextor/busca-processos-judiciais"&gt;Github do projeto&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/busca-processos-judiciais"&gt;NPM&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.tabnews.com.br/NewsletterOficial/cnj-lanca-a-api-publica-do-datajud-oferecendo-acesso-geral-aos-metadados-de-processos-judiciais-em-todo-o-brasil"&gt;Notícia oficial postada aqui no Tabnews&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Convidem seus amigos, familiares e pets para contribuir com o crescimento do projeto 😃&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>api</category>
      <category>programming</category>
    </item>
    <item>
      <title>Stop Manually Uploading Your Site To The Hosting Service</title>
      <dc:creator>João Textor</dc:creator>
      <pubDate>Sat, 14 Oct 2023 19:00:00 +0000</pubDate>
      <link>https://dev.to/joaotextor/stop-manually-uploading-your-site-to-the-hosting-service-3c64</link>
      <guid>https://dev.to/joaotextor/stop-manually-uploading-your-site-to-the-hosting-service-3c64</guid>
      <description>&lt;p&gt;So, you are done creating or editing a website and now you need to upload it to your hosting service. What is your next step?&lt;/p&gt;

&lt;p&gt;Let me answer that: there was a time when I uploaded all my files to the shared hosting service using a FTP Client. I needed to open the client, login, search for the folder I wanted to upload in, and then drag all the website files into it.&lt;/p&gt;

&lt;p&gt;If you identify yourself in this routine, I say those days are over!&lt;/p&gt;

&lt;p&gt;Let's create, today, a very simple script to automate this boring work.&lt;/p&gt;

&lt;p&gt;Just like in the &lt;a href="https://dev.to/joaotextor/using-github-actions-to-publish-a-node-package-automatically-kgp"&gt;last week's post&lt;/a&gt;, we'll be using GitHub Actions to perform this automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Setting up the environment
&lt;/h2&gt;

&lt;p&gt;If your project is not yet on GitHub, let's start by publishing it.&lt;/p&gt;

&lt;p&gt;Then create a YAML file in your project's repository under the .github/workflows directory. You can name the file something like &lt;code&gt;publish-ftp.yml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;└── .github
    └── workflows
        └── publish-ftp.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is going to be the content of your YAML file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🚀 Deploy website on push&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web-deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🎉 Deploy&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🚚 Get latest code&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;📂 Sync files&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SamKirkland/FTP-Deploy-Action@v4.3.4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.FTP_SERVER }}&lt;/span&gt;
          &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.FTP_USERNAME }}&lt;/span&gt;
          &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.FTP_PASSWORD }}&lt;/span&gt;
          &lt;span class="na"&gt;server-dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/path/to/your/project&lt;/span&gt;
          &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;README.md&lt;/span&gt;
            &lt;span class="s"&gt;.editorconfig&lt;/span&gt;
            &lt;span class="s"&gt;**/.git*/**&lt;/span&gt;
            &lt;span class="s"&gt;**/.git*&lt;/span&gt;
            &lt;span class="s"&gt;**/node_modules/**&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Understanding the configuration
&lt;/h2&gt;

&lt;p&gt;This YAML file is pretty straightforward: we start by defining that the workflow should run on each &lt;code&gt;push&lt;/code&gt; to the repository and it will only run on &lt;code&gt;main&lt;/code&gt; branch. Then, there's the usual code for configuring GitHub Actions and the configuration to use the FTP-Deploy-Action from SamKirkland.&lt;/p&gt;

&lt;p&gt;Next, we will...&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Set up the secrets
&lt;/h2&gt;

&lt;p&gt;In here, we have 3 secret keys we must setup before committing and pushing to our remote repository.&lt;/p&gt;

&lt;p&gt;Follow these steps:&lt;br&gt;
a. Go to your GitHub repository.&lt;br&gt;
b. Click on the "Settings" tab.&lt;br&gt;
c. In the left sidebar, click on "Secrets and variables" and then "Actions".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XzV9rhLo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1g7w0wwgpgvibwkimjlq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XzV9rhLo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1g7w0wwgpgvibwkimjlq.png" alt="Image description" width="310" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;github actions&lt;br&gt;
d. Click the "New repository secret" button.&lt;br&gt;
e. Name the secret "FTP_SERVER".&lt;br&gt;
f. Paste the URL to your ftp server.&lt;br&gt;
g. Click "Add secret" to save it.&lt;br&gt;
h. Repeat with the other 2 keys, providing your credentials.&lt;/p&gt;

&lt;p&gt;Also, don't forget to inform the exact path to your project inside your server on &lt;code&gt;server-dir&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;Now that everything is set up correctly, it's time to commit your changes, push to your repository and wait for the ninja cats from GitHub to do their work 🐱!&lt;/p&gt;

&lt;p&gt;See ya and until the next post!&lt;/p&gt;

</description>
      <category>ftp</category>
      <category>webdev</category>
      <category>githubactions</category>
      <category>github</category>
    </item>
    <item>
      <title>Using GitHub Actions to Publish a Node Package Automatically</title>
      <dc:creator>João Textor</dc:creator>
      <pubDate>Sun, 08 Oct 2023 16:00:00 +0000</pubDate>
      <link>https://dev.to/joaotextor/using-github-actions-to-publish-a-node-package-automatically-kgp</link>
      <guid>https://dev.to/joaotextor/using-github-actions-to-publish-a-node-package-automatically-kgp</guid>
      <description>&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
GitHub Actions have revolutionized the way we automate workflows in our projects. In this guide, we'll explore how to use GitHub Actions to automatically publish your Node package to npmjs.com, simplifying the release process, since the GitHub cats will take care of the job 🐱.&lt;/p&gt;

&lt;p&gt;With this setup, you can ensure that your package stays up to date without manual intervention (may be a paw-intervention). Let's get started with the step-by-step process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iqZ67T-I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/79b4t2y8amffijnxesf2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iqZ67T-I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/79b4t2y8amffijnxesf2.jpg" alt="Cat working" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Publish Your Code GitHub Repository&lt;/li&gt;
&lt;li&gt;Create an NPM Token on npmjs.com&lt;/li&gt;
&lt;li&gt;Create a GitHub Secret with Your NPM Token&lt;/li&gt;
&lt;li&gt;Create a YAML File&lt;/li&gt;
&lt;li&gt;
Configuring the Workflow

&lt;ul&gt;
&lt;li&gt;Brief Explanation of the Code&lt;/li&gt;
&lt;li&gt;Guidelines&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Wrapping Up&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  1. Publish Your Code GitHub Repository&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Before we dive into the automation, make sure your code is hosted on GitHub. If it's not already, create a repository for your Node.js project and push your code to it.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Create an NPM Token on npmjs.com&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To publish packages to npmjs.com, you need an authentication token. Here's how to create one:&lt;/p&gt;

&lt;p&gt;a. Visit npmjs.com.&lt;br&gt;
b. Log in to your npmjs.com account.&lt;br&gt;
c. Click on your profile picture in the upper right corner and select "Access Tokens."&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fKAwzAtu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmyaaaiz56asjnwqw8iv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fKAwzAtu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmyaaaiz56asjnwqw8iv.png" alt="npmjs.com menu" width="220" height="293"&gt;&lt;/a&gt;&lt;br&gt;
d. Click the "Generate New Token" button and select "Classic Token".&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zhofRvTH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efnqznxxfe2hvnmf2z3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zhofRvTH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efnqznxxfe2hvnmf2z3w.png" alt="create token button" width="206" height="138"&gt;&lt;/a&gt;&lt;br&gt;
e. Provide a Name for your token, such as "GitHub Actions Token."&lt;br&gt;
f. Select the "Automation" permission.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oPaXIvrm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ycugwjdesb829ae0qibf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oPaXIvrm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ycugwjdesb829ae0qibf.png" alt="select permissions" width="643" height="270"&gt;&lt;/a&gt;&lt;br&gt;
g. Click "Generate Token."&lt;br&gt;
h. Keep your generated token secure; you won't be able to see it again.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Create a GitHub Secret with Your NPM Token&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;a. Go to your GitHub repository.&lt;br&gt;
b. Click on the "Settings" tab.&lt;br&gt;
c. In the left sidebar, click on "Secrets and variables" and then "Actions".&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CHYKt4oa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gehcnnemkd7dixusx6q2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CHYKt4oa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gehcnnemkd7dixusx6q2.png" alt="github actions" width="310" height="127"&gt;&lt;/a&gt;&lt;br&gt;
d. Click the "New repository secret" button.&lt;br&gt;
e. Name the secret "NPM_TOKEN".&lt;br&gt;
f. Paste the npm token you generated in the previous step into the "Value" field.&lt;br&gt;
g. Click "Add secret" to save it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Create an YAML file&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We'll now set up a workflow to automate the package publishing process. Start by creating a YAML file in your project's repository under the .github/workflows directory. You can name the file something like npm-publish.yml.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;└── .github
    └── workflows
        └── npm-publish.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuring the workflow&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Now, inside your YAML file, paste the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;publish&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;checkout repo&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;setup node&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;18.x&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;npm"&lt;/span&gt;
          &lt;span class="na"&gt;registry-url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://registry.npmjs.org/"&lt;/span&gt;

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

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;increment version&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git config user.email "&amp;lt;YOUR_EMAIL&amp;gt;" &amp;amp;&amp;amp; git config user.name "&amp;lt;YOUR_NAME&amp;gt;" &amp;amp;&amp;amp; npm version patch&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;run tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run lint &amp;amp;&amp;amp; npm run test&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build package&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run build&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;publish package&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm set "//registry.npmjs.org/:_authToken" ${{ secrets.NPM_TOKEN }} &amp;amp;&amp;amp; npm publish -access public&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Brief explanation of the code&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We have set up the workflow to run on every "push" to the repository, and it will run only on the "master" branch.&lt;/p&gt;

&lt;p&gt;Next, we have set up the jobs with some standard GitHub actions configuration, setting up the node version and the "registry-url" from npmjs.org.&lt;/p&gt;

&lt;p&gt;The workflow continues by installing dependencies, incrementing your package version (See details below), running the tests, building the package from our source code and finally publishing the package to npmjs.com.&lt;/p&gt;

&lt;h3&gt;
  
  
  Guidelines&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; To ensure this workflow functions properly, you MUST have setup your &lt;code&gt;package.json&lt;/code&gt; file before accordingly to this post: &lt;a href="https://dev.to/joaotextor/building-and-publishing-your-own-node-library-package-created-with-typescript-591d"&gt;Building and Publishing Your TypeScript Code as a NPM Package&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure you replace &lt;code&gt;&amp;lt;YOUR_EMAIL&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;YOUR_NAME&amp;gt;&lt;/code&gt; with your email and name, respectively, since the command &lt;code&gt;npm version patch&lt;/code&gt; will need to change your &lt;code&gt;package.json&lt;/code&gt; file inside your repository.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can replace &lt;code&gt;npm version &amp;lt;patch&amp;gt;&lt;/code&gt; with any other &lt;code&gt;&amp;lt;property&amp;gt;&lt;/code&gt; as stated on &lt;a href="https://docs.npmjs.com/cli/v8/commands/npm-version"&gt;npm's official documentation&lt;/a&gt;; this is up to you.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Wrapping up&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;So, in this post we saw how you can automate the workflow of building and publishing a package to npmjs.com using GitHub Actions.&lt;/p&gt;

&lt;p&gt;Next week I'll explore more this amazing feature from GitHub and use it to deploy a website to a shared hosting service (such as Hostinger, HostGator and so on...).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I was supposed to publish this article next Tuesday, but as I'm new to dev.to I decided to play a little with the posting dates/hours.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hope you all enjoyed reading this and learnt something new 😄&lt;/p&gt;

&lt;p&gt;Scroll to top&lt;/p&gt;

</description>
      <category>node</category>
      <category>githubactions</category>
      <category>npm</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building and Publishing Your TypeScript Code as a NPM Package</title>
      <dc:creator>João Textor</dc:creator>
      <pubDate>Tue, 03 Oct 2023 19:00:00 +0000</pubDate>
      <link>https://dev.to/joaotextor/building-and-publishing-your-own-node-library-package-created-with-typescript-591d</link>
      <guid>https://dev.to/joaotextor/building-and-publishing-your-own-node-library-package-created-with-typescript-591d</guid>
      <description>&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;br&gt;
I love open-source software. The previous couple of weeks, I posted about &lt;a href="https://dev.to/joaotextor/how-to-write-a-key-generator-in-typescript-3049"&gt;how I created a key generator&lt;/a&gt; and &lt;a href="https://dev.to/joaotextor/using-jest-to-bulletproof-a-typescript-class-part-1-hjo"&gt;how I tested the code&lt;/a&gt; using jest.&lt;/p&gt;

&lt;p&gt;Today, time has come to publish that code as a library on npmjs.com, so it can be consumed by anyone.&lt;/p&gt;

&lt;p&gt;Are you ready for this?&lt;/p&gt;
&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TL;DR&lt;/li&gt;
&lt;li&gt;First, the requirements&lt;/li&gt;
&lt;li&gt;Dependency installing&lt;/li&gt;
&lt;li&gt;Logging in to npm&lt;/li&gt;
&lt;li&gt;Configuring tsconfig.json&lt;/li&gt;
&lt;li&gt;
Configure package.json

&lt;ul&gt;
&lt;li&gt;Explaining the &lt;code&gt;npx fix-tsup-cjs&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Building our project&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Publishing&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  TL;DR&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;(Scroll to Top)&lt;/p&gt;

&lt;p&gt;This article explains how to publish a TypeScript project as an open-source library on npmjs.com. It covers the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure you have an npmjs.com account and a suitable npm version.&lt;/li&gt;
&lt;li&gt;Install the &lt;code&gt;tsup&lt;/code&gt; library for bundling TypeScript projects.&lt;/li&gt;
&lt;li&gt;Log in to your npmjs.com account using the npm CLI.&lt;/li&gt;
&lt;li&gt;Configure your tsconfig.json file with specific options.&lt;/li&gt;
&lt;li&gt;Set up your package.json file with essential package details.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;fix-tsup-cjs&lt;/code&gt; library to improve CommonJS module usage.&lt;/li&gt;
&lt;li&gt;Build your project with &lt;code&gt;npm run build&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Test the installation with &lt;code&gt;npm install . -g&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Finally, publish your package to npmjs.com with &lt;code&gt;npm publish&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  First, the requirements&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;(Scroll to Top)&lt;/p&gt;

&lt;p&gt;First of all, before we start the publishing process, we need to make sure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We've created and account on npmjs.com.&lt;/li&gt;
&lt;li&gt;Our npm version is at least 9.8 (I've used 10.1, but 9.8 is fine)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Dependency installing&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;(Scroll to Top)&lt;/p&gt;

&lt;p&gt;We are going to use a library called &lt;code&gt;tsup&lt;/code&gt; to bundle our TypeScript project. So, make sure you install it by running:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install tsup --save&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Logging in to npm&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;(Scroll to Top)&lt;/p&gt;

&lt;p&gt;After you've created your account on npmjs.com, login to it using the npm cli. You can type it using the terminal inside VS Code if you want:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm login&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After hitting 'Enter', you'll see the following message.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ftuvgt4zstoug7mdkd8vd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ftuvgt4zstoug7mdkd8vd.png" alt="Terminal message saying to hit Enter to open the browser"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just hit 'Enter' again to open the login page in your web browser. You will receive an One-time Password, so check your email and paste it in the form.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fbxb8hsfc7l5jco8ydjmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbxb8hsfc7l5jco8ydjmd.png" alt="Web page asking for the One-time password"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your CLI should show a message like this: &lt;code&gt;Logged in on https://registry.npmjs.org/.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You are good to continue!&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuring tsconfig.json&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;(Scroll to Top)&lt;/p&gt;

&lt;p&gt;Here we are making some configuration so &lt;code&gt;tsup&lt;/code&gt; creates the bundle correctly.&lt;/p&gt;

&lt;p&gt;Here are the options you should enable in your tsconfig.json (some may already be enabled):&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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;compilerOptions&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="cm"&gt;/* Language and Environment */&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;target&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ES2016&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="cm"&gt;/* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="cm"&gt;/* Modules */&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CommonJS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="cm"&gt;/* Specify what module code is generated. */&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;noEmit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="cm"&gt;/* Disable emitting files from a compilation. */&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;esModuleInterop&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="cm"&gt;/* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;forceConsistentCasingInFileNames&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="cm"&gt;/* Ensure that casing is correct in imports. */&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="cm"&gt;/* Type Checking */&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;strict&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="cm"&gt;/* Enable all strict type-checking options. */&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;noUncheckedIndexedAccess&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="cm"&gt;/* Add 'undefined' to a type when accessed using an index. */&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;skipLibCheck&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="cm"&gt;/* Skip type checking all .d.ts files. */&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;include&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="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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;exclude&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node_modules&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// which files to skip&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure package.json&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;(Scroll to Top)&lt;/p&gt;

&lt;p&gt;Configuring the &lt;code&gt;package.json&lt;/code&gt; file correctly is a crucial part in packaging and publishing your code to npmjs.com, so I will briefly describe the configurations I make.&lt;/p&gt;

&lt;p&gt;First, let's see the configuration file, and later I will explain it.&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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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="s2"&gt;easy-key-generator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.1.9&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Easy library for generating secret keys.
It supports various features like groups, separators,
key format, and the possibility of generating multiples
keys at once.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist/index.mjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist/index.d.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;files&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tsc --watch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tsup index.ts --format cjs,esm --dts &amp;amp;&amp;amp; npx fix-tsup-cjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tsc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;João Textor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;license&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MIT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;repository&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;git&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://github.com/joaotextor/easy-key-generator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keywords&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;key generator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;code generator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;devDependencies&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@types/jest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^29.5.5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@typescript-eslint/eslint-plugin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^6.7.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@typescript-eslint/parser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^6.7.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eslint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^8.49.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^29.7.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prettier&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^3.0.3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ts-jest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^29.1.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tsup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^7.2.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;typescript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^5.2.2&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;
&lt;strong&gt;name&lt;/strong&gt; is the name of your package. Try choosing an unique one. Search for existing packages in npmjs.com.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;version&lt;/strong&gt;: self-explanatory. I started with 1.0.0, but you're free to choose what you want. Be aware that each time you publish to npmjs.com, the next time it must contain a newer version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;description&lt;/strong&gt;: this is where you briefly describe what your packages does.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;main&lt;/strong&gt;: this is where you declare the path to your main bundled file (which not yet exists). This is the javascript file which users will import using &lt;code&gt;import&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;module&lt;/strong&gt;: this is the bundled javascript file to be imported using &lt;code&gt;require&lt;/code&gt;, as a commonJS module.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;types&lt;/strong&gt;: the path to your &lt;code&gt;d.ts&lt;/code&gt; file, which contains your types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;scripts&lt;/strong&gt;: here we created a &lt;code&gt;build&lt;/code&gt; script that will call &lt;code&gt;tsup&lt;/code&gt; to bundle our &lt;code&gt;index.ts&lt;/code&gt;, which is our project's main file; we've passed the option --format with &lt;code&gt;cjs,esm&lt;/code&gt; params, which will create the commonJS file and a ES Module file; finally, the --dts option is telling &lt;code&gt;tsup&lt;/code&gt; to create our type file with &lt;code&gt;d.ts&lt;/code&gt; extension. Next we will call &lt;code&gt;npx fix-tsup-cjs&lt;/code&gt;. Why? I'll explain later on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;author&lt;/strong&gt;: This is where you put your name, so everyone can blame you publicly if your library introduce bugs into their projects (just kidding...or not!)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;license&lt;/strong&gt;: You can inform an open-source license here if you want.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;repository&lt;/strong&gt;: want to make easier for people to yell at you online? Place the repository to your library here 😅. They might also submit a PR to fix your undesired bugs 😄.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Explaining the &lt;code&gt;npx fix-tsup-cjs&lt;/code&gt;&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;(Scroll to Top)&lt;/p&gt;

&lt;p&gt;When bundling your project using &lt;code&gt;tsup&lt;/code&gt;, you might notice that when importing the CommonJs module using something like &lt;code&gt;const KeyGenerator = require("easy-key-generator");&lt;/code&gt; when calling your class' constructor you must type this: &lt;code&gt;new KeyGenerator.default()&lt;/code&gt;. Also, when calling a method, let's say &lt;code&gt;generate()&lt;/code&gt;, you need to call it by using &lt;code&gt;KeyGenerator.default().generate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This sucks, right? Why can't you instantiate your class by using only &lt;code&gt;KeyGenerator()&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Well, the library &lt;a href="https://github.com/u3u/fix-tsup-cjs" rel="noopener noreferrer"&gt;&lt;code&gt;fix-tsup-cjs&lt;/code&gt;&lt;/a&gt; enables you to do exactly that, that's why we executed it after bundling our project using &lt;code&gt;tsup&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building our project&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;(Scroll to Top)&lt;/p&gt;

&lt;p&gt;Well, now that everything is setup correctly, is time for us to build our project.&lt;/p&gt;

&lt;p&gt;Just type &lt;code&gt;npm run build&lt;/code&gt; in your terminal in the root of your project and hit 'Enter'.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;(Scroll to Top)&lt;/p&gt;

&lt;p&gt;Before publishing the package, your should test installing it.&lt;/p&gt;

&lt;p&gt;To test the install, type &lt;code&gt;npm install . -g&lt;/code&gt; in the root of your project. NPM should be able to install it globally as any other package.&lt;/p&gt;

&lt;p&gt;If anything goes wrong in this step, it means something is wrong with your configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publishing&lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;(Scroll to Top)&lt;/p&gt;

&lt;p&gt;Finally, it's time to publish your package to npmjs.com. Type &lt;code&gt;npm publish&lt;/code&gt;, get your fingers crossed and TA-DA!&lt;/p&gt;

&lt;p&gt;Congratulations, you've successfully published your TypeScript code to npmjs.com! It is now available to the npm community. &lt;/p&gt;

&lt;p&gt;In this guide, we've covered the essential steps to publish your TypeScript project on npmjs.com. By following these steps and maintaining your package, you can share your code with the world and contribute to the open-source community. Happy coding!&lt;/p&gt;

&lt;p&gt;If you did read through the entire post until here, please leave a reaction and a comment, and hit the follow button because &lt;strong&gt;next week we will be learning how to automatize the work of publishing a node package by using GitHub Actions!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Until next week!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>npm</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Using Jest to bulletproof a TypeScript Class - Part 2</title>
      <dc:creator>João Textor</dc:creator>
      <pubDate>Tue, 26 Sep 2023 22:00:00 +0000</pubDate>
      <link>https://dev.to/joaotextor/using-jest-to-bulletproof-a-typescript-class-part-2-1njf</link>
      <guid>https://dev.to/joaotextor/using-jest-to-bulletproof-a-typescript-class-part-2-1njf</guid>
      <description>&lt;p&gt;The second and final part of our testing suite is here!&lt;br&gt;
Check out the first part &lt;a href="https://dev.to/joaotextor/using-jest-to-bulletproof-a-typescript-class-part-1-hjo"&gt;HERE&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We will continue testing our &lt;code&gt;generate&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Here we'll test generating a code with 2 groups and the default separator.&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should generate a code with 2 groups and the default group separator&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CodeGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;    
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&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="nx"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&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="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nx"&gt;toBe&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our &lt;code&gt;code&lt;/code&gt; will still have the length of 1, and the first index will have a length of 11, since the key has 2 groups of 5 characters, additionally to the separator &lt;code&gt;"-"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we will modify our configuration, this time using the &lt;code&gt;"_"&lt;/code&gt; character as the group separator. We're testing if the &lt;code&gt;CodeGenerator&lt;/code&gt; respects our choice of separator.&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should generate a code with 2 groups and the '_' 'groupSeparator'&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CodeGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;groupSeparator&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&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="nx"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&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="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nx"&gt;toBe&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next test will analyze the generation of 2 keys at the same time.&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should generate 2 random keys&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CodeGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;numberOfKeys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&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="nx"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nx"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As expected, the &lt;code&gt;code&lt;/code&gt; Array will have 2 items, and each of them a length of 5.&lt;/p&gt;

&lt;p&gt;We also need to test generating keys with a different &lt;code&gt;characterType&lt;/code&gt;, which is done in the following test:&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should generate 1 key with only numbers&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CodeGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;characterType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Numbers&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;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&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;numberCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&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="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numberCode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toBeNaN&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we converted our generated code (which is a string inside an Array) into a number, and test if the result is an actual number or it returned &lt;code&gt;NaN&lt;/code&gt; in the type conversion.&lt;/p&gt;

&lt;p&gt;Our next test will analyze if our code will give priority to the length of &lt;code&gt;groupFormat&lt;/code&gt; over the length informed in the first property when instantiating a class.&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should generate a key with 'groupFormat' length instead of the length informed.&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CodeGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;characterType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LettersAndNumbers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;groupFormat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NNLNLLN&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;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&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="nx"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&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;Our &lt;code&gt;groupFormat&lt;/code&gt; have a length of 7, but we passed the number 5 for the property of &lt;code&gt;numbersOfCharacters&lt;/code&gt;. Our logic demands that when the &lt;code&gt;groupFormat&lt;/code&gt; is informed, the output group should have the length of the group format informed.&lt;/p&gt;

&lt;p&gt;Finally, to our last test, we will verify if the &lt;code&gt;groupFormat&lt;/code&gt; informed by the developer is actually being respected in the output.&lt;/p&gt;

&lt;p&gt;In short, if the &lt;code&gt;grouptFormat&lt;/code&gt; is &lt;code&gt;"LLNLN"&lt;/code&gt;, the output should be something like this: "ZH8D2".&lt;/p&gt;

&lt;p&gt;This is going to be a more complex test than the others, since we will have to convert our string key to an Array and iterate this Array to see if it is a number or not.&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should generate a key with the format informed in 'groupFormat' property. &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="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;groupFormat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LLNLN&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;groupFormatArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;groupFormat&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;sut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CodeGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;groupFormat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;groupFormat&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;codes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&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;codeArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;codes&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="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;codeArray&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;codeChar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;codeArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;char&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;groupFormatArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;L&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;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;codeChar&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBeNaN&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="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;codeChar&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toBeNaN&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this final test, we finished our suite of unit tests for the &lt;code&gt;CodeGenerator&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;This is going to be the last post in this series. However, next week I will open a new series with an article on how I published the Easy Key Generator to npmjs.com as a library that can be used by anyone. Hit the follow button to stay tuned in future posts. &lt;/p&gt;

&lt;p&gt;Talk to you all next week, and do not forget to react to this post and comment if you have any suggestions or to make any constructive criticisms :-)&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>testing</category>
      <category>typescript</category>
      <category>jest</category>
    </item>
    <item>
      <title>Using Jest to bulletproof a TypeScript Class - Part 1</title>
      <dc:creator>João Textor</dc:creator>
      <pubDate>Tue, 26 Sep 2023 19:00:00 +0000</pubDate>
      <link>https://dev.to/joaotextor/using-jest-to-bulletproof-a-typescript-class-part-1-hjo</link>
      <guid>https://dev.to/joaotextor/using-jest-to-bulletproof-a-typescript-class-part-1-hjo</guid>
      <description>&lt;p&gt;Hello, my fellow developers.&lt;/p&gt;

&lt;p&gt;In my &lt;a href="https://dev.to/joaotextor/how-to-write-a-key-generator-in-typescript-3049"&gt;previous post&lt;/a&gt;, I wrote about how to develop a simple and easy tool for generating keys for you to use in your projects.&lt;/p&gt;

&lt;p&gt;As I wanted to publish it as a package on npmjs.com, I needed to write some tests to ensure everything was running smoothly in every situation.&lt;/p&gt;

&lt;p&gt;Picture this: You've spent some time crafting a TypeScript library, meticulously designing its features. However, before you unleash your creation upon the world, you need to ensure that it's as robust as a tank and as reliable as your grandma's secret cookie recipe, right?&lt;/p&gt;

&lt;p&gt;So I chose Jest.js, the trusty sidekick of TypeScript developers, ready to assist in the quest for bulletproof code. &lt;/p&gt;

&lt;p&gt;In this post, we're going to start crafting a series of unit tests using Jest.js to ensure our Key Generator tool behaves impeccably.&lt;/p&gt;

&lt;p&gt;I decided to split this into a 2-part article because it ended up being too long.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the &lt;code&gt;validateGroupFormat&lt;/code&gt; method
&lt;/h2&gt;

&lt;p&gt;Our first group of tests will focus on our private method &lt;code&gt;validateGroupFormat&lt;/code&gt;, guaranteeing it throw the errors when needed.&lt;/p&gt;

&lt;p&gt;Let's start by setting the stage for our tests by writing 2 &lt;code&gt;describe&lt;/code&gt;s, thus creating 2 context blocks for our actual tests.&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="nx"&gt;CodeGenerator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ICodeGenerator&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;../index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Key Generator Tests&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Testing 'validateGroupFormat' errors and warnings'&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ICodeGenerator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Our tests will be written 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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to import our dependencies: the &lt;code&gt;CodeGenerator&lt;/code&gt; class and our interface &lt;code&gt;ICodeGenerator&lt;/code&gt;, since our &lt;code&gt;sut&lt;/code&gt; (system under test) should have this type.&lt;/p&gt;

&lt;p&gt;Also, we are not going to call the actual &lt;code&gt;validateGroupFormat&lt;/code&gt;, but test its functionality by actual calling our &lt;code&gt;generate&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Now, let's see our first test.&lt;/p&gt;

&lt;h3&gt;
  
  
  Empty &lt;code&gt;groupFormat&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When a developer uses the CodeGenerator class without specifying the groupFormat, we don't want to pester them with unnecessary validation checks. Instead, we choose to be polite and silently skip the validation process.&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should skip validation if 'groupFormat' was not informed by the user&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CodeGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&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;consoleSpy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spyOn&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;log&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;consoleSpy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Group Format is not defined, skipping validation.&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;If you don't remember or didn't read my last post, I suggest you take a quick look at it by &lt;a href="https://dev.to/joaotextor/how-to-write-a-key-generator-in-typescript-3049"&gt;clicking here&lt;/a&gt; so you can get familiar with the code being tested.&lt;/p&gt;

&lt;p&gt;So, when the &lt;code&gt;groupFormat&lt;/code&gt; is empty this validation will simply call a console.log with the message 'Group Format is not defined, skipping validation.'.&lt;/p&gt;

&lt;p&gt;Therefore, we used the 'spyOn' method on Jest to watch if the "log" method of the &lt;code&gt;console&lt;/code&gt; was being called when we generate a new code.&lt;/p&gt;

&lt;p&gt;You may be wondering why we even called our  &lt;code&gt;validateGroupFormat&lt;/code&gt; auxiliary method in the first place if the user did not inform the &lt;code&gt;groupFormat&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;Well, we did this to comply with the first principle of SOLID: single responsibility. We could have actually checked if the &lt;code&gt;groupFormat&lt;/code&gt; was empty before calling the validation method, but that would mean the &lt;code&gt;generate&lt;/code&gt; method would also be doing its own validations, and this can get confusing. Of course this is a very small project, but it's important to follow a clean code pattern even when we are working on small pieces of code, so others (and your future self) can properly understand what the code is doing.&lt;/p&gt;

&lt;p&gt;With that clear, let's jump to the other test.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;groupFormat&lt;/code&gt; being passed with the wrong type of &lt;code&gt;characterType&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;groupFormat&lt;/code&gt; purpose is to let the user customize the order of characters (Letters or Numbers) in the output key.&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should throw an error when 'groupFormat' is used with 'characterType' other than 'LettersAndNumbers'&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nx"&gt;sut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CodeGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;characterType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Letters&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;groupFormat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NNLNL&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;expect&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;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;toThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&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;The groupFormat can only be used with 'LettersAndNumbers' characterType!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, in our second test, we don our detective hats to catch developers trying to mix incompatible options. Thus, we test by passing &lt;code&gt;"Letters"&lt;/code&gt; to &lt;code&gt;characterType&lt;/code&gt; property and at the same time we configure our output to have a &lt;code&gt;groupFormat&lt;/code&gt; of &lt;code&gt;"NNLNL"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The test is pretty simple. It ensures that our code enforces rules consistently, preventing developers from using incompatible settings that could lead to unexpected behavior.&lt;/p&gt;

&lt;p&gt;One thing to notice here is that &lt;strong&gt;we have called &lt;code&gt;sut.generate&lt;/code&gt; inside a anonymous function&lt;/strong&gt;. If you don't do that, the test will not run due the &lt;code&gt;Error&lt;/code&gt; being actually thrown.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;groupFormat&lt;/code&gt; contains invalid characters
&lt;/h3&gt;

&lt;p&gt;The third and final test for our validation method is all about maintaining order on our key generation tool. We won't tolerate any rogue characters sneaking into the &lt;code&gt;groupFormat&lt;/code&gt;. If a developer dares to include characters other than 'L' (for letters) or 'N' (for numbers), our code will not hesitate to raise the alarm.&lt;/p&gt;

&lt;p&gt;The code for our test is the following:&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should throw error when 'groupFormat' has any characters other than 'L' or 'N'&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CodeGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;characterType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LettersAndNumbers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;groupFormat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LLLLB&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;expect&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;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;toThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&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;The group format can only contain letters 'L' and numbers 'N'&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The validation here is similar to the one being made in the previous test.&lt;br&gt;
Our validation method is using a RegEx statement to match our string, as seen in the previous post.&lt;/p&gt;

&lt;p&gt;Here we passed the string &lt;code&gt;"LLLLB"&lt;/code&gt;, so our code successfully throws an error when trying to generate a key.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;generate&lt;/code&gt; method
&lt;/h2&gt;

&lt;p&gt;To void making this post too long, I will place only the first test for the &lt;code&gt;generate&lt;/code&gt; method. The second part is going to address the rest of the tests.&lt;/p&gt;
&lt;h3&gt;
  
  
  Generating a random key with the default settings
&lt;/h3&gt;

&lt;p&gt;What a better way of starting our tests for the &lt;code&gt;generate&lt;/code&gt; method if not by actual generating a key, right?&lt;/p&gt;

&lt;p&gt;We are going to start with the default settings (no props being passed).&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should generate a random code with the default options&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CodeGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&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;randomSpy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;spyOn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;random&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;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;randomSpy&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveBeenCalledTimes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&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="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&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="nx"&gt;toHaveLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are asking our "System Under Test" to generate a 5-character key.&lt;br&gt;
We're also using Jest's &lt;code&gt;spyOn&lt;/code&gt; to watch on the &lt;code&gt;random&lt;/code&gt; method of the &lt;code&gt;Math&lt;/code&gt; library.&lt;/p&gt;

&lt;p&gt;Our &lt;code&gt;code&lt;/code&gt;, which is an Array, should have a length of 1 and the length of the key needs to be of 5 characters. Hence, logic requires that the &lt;code&gt;random&lt;/code&gt; method is being called 5 times as well.&lt;/p&gt;

&lt;p&gt;In the next post, which is going live a few hours after this one, we are going to address the rest of our tests.&lt;/p&gt;

&lt;p&gt;Hope y'all enjoyed this first part.&lt;br&gt;
I'll be glad to read your thoughts.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>testing</category>
      <category>javascript</category>
      <category>jest</category>
    </item>
    <item>
      <title>How to Write a Key Generator using TypeScript</title>
      <dc:creator>João Textor</dc:creator>
      <pubDate>Tue, 19 Sep 2023 18:45:00 +0000</pubDate>
      <link>https://dev.to/joaotextor/how-to-write-a-key-generator-in-typescript-3049</link>
      <guid>https://dev.to/joaotextor/how-to-write-a-key-generator-in-typescript-3049</guid>
      <description>&lt;p&gt;Are you looking to create a custom key generator in TypeScript for your next project? Whether it's for generating secure API keys or unique identifiers, this type of function can be very useful. &lt;/p&gt;

&lt;p&gt;In this step-by-step tutorial, I'll walk you through the process of how I built a TypeScript key generator from scratch.&lt;/p&gt;

&lt;p&gt;The inspiration for this code came from &lt;a href="https://www.youtube.com/watch?v=pb4ggtC1Mh8"&gt;this video (in Portuguese)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A disclaimer, though: as very well pointed in the comments, &lt;strong&gt;this is not a script for generating security keys&lt;/strong&gt; (like API keys, etc). I got the idea for this from a YT in which they used an app for generating code for in-person sweepstakes. You can adapt it using &lt;code&gt;Crypto&lt;/code&gt; module from Node.js or another JS runtime so it can be secure.&lt;/p&gt;

&lt;p&gt;Also, I know there's a lot of libraries out there for generating keys and security hashes, but I deliberately didn't search them before implementing my idea so it didn't become biased by other's  ideas. In short, this small project served more as a challenge for myself than anything else, like making a robust key and secure generator, which was not the goal.&lt;/p&gt;

&lt;p&gt;Be aware that this is my &lt;em&gt;first post&lt;/em&gt; here on dev.to, and actually my first time trying to explain a code to others, which is harder than writing in the coding journal I keep to my future-self.&lt;/p&gt;

&lt;p&gt;Also, it has been less than an year I started studying Javascript and Typescript, so there might be some ugly code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The File Structure&lt;/li&gt;
&lt;li&gt;Step 1: Defining the Types&lt;/li&gt;
&lt;li&gt;Step 2: Creating the Key Generator Class&lt;/li&gt;
&lt;li&gt;Step 3: Defining and implementing an auxiliary method&lt;/li&gt;
&lt;li&gt;Step 4: Implementing our Main Method&lt;/li&gt;
&lt;li&gt;Final Step: Generating Keys&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The File Structure &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;After I wrote this tutorial, I realized it could be confusing not knowing how the project was structured beforehand. So here are the files and folders of our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── index.ts
└── utils
    ├── charactersByType.ts
    └── types
        ├── characterType.ts
        └── separatorType.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1: Defining the Types &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Character Types
&lt;/h3&gt;

&lt;p&gt;Before we dive into the key generation logic, let's start by defining the types of characters we want to include in our keys. &lt;/p&gt;

&lt;p&gt;I did this by creating a file called &lt;code&gt;characterType.ts&lt;/code&gt; inside the folder utils/types. Here's the code for this 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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;charType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Letters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Letters&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;Numbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Numbers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;LettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LettersAndNumbers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;HexChar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HexChar&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="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;characterType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;charType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In this code snippet, we defined a set of character types such as "Letters," "Numbers," "LettersAndNumbers," and "HexChar" using TypeScript's const assertion. We also create a type characterType which is a union of all the keys of the charType object. These character types will be crucial for generating diverse and customizable keys in later steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Character Sets
&lt;/h3&gt;

&lt;p&gt;Now we'll create a file named &lt;code&gt;charactersByType.ts&lt;/code&gt; to define different character sets based on the &lt;code&gt;characterType&lt;/code&gt; selected. Here's the code for &lt;code&gt;charactersByType.ts&lt;/code&gt;:&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;charactersByType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Letters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ABCDEFGHIJKLMNOPQRSTUVWXYZ&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;LettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;Numbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0123456789&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;HexChar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0123456789ABCDEF&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 this code snippet, we've defined four character sets:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Letters&lt;/strong&gt;: Contains uppercase English letters.&lt;br&gt;
&lt;strong&gt;LettersAndNumbers&lt;/strong&gt;: Combines uppercase letters and numbers.&lt;br&gt;
&lt;strong&gt;Numbers&lt;/strong&gt;: Contains only numerical digits.&lt;br&gt;
&lt;strong&gt;HexChar&lt;/strong&gt;: Includes hexadecimal characters (0-9 and A-F).&lt;/p&gt;

&lt;p&gt;These character sets will determine the available characters for generating keys.&lt;/p&gt;
&lt;h3&gt;
  
  
  Separators
&lt;/h3&gt;

&lt;p&gt;We'll also define the separators that can be used to separate groups of characters within a key. Create a file named &lt;code&gt;separatorType.ts&lt;/code&gt; with the following code:&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;export&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;separatorType&lt;/span&gt; &lt;span class="o"&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="o"&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="o"&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="o"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we've defined a type &lt;code&gt;separatorType&lt;/code&gt; that represents four possible separators: hyphen (-), underscore (_), period (.), and space ( ). Feel free to include any characters you might want.&lt;/p&gt;

&lt;p&gt;With our character sets and separators defined, we're ready to move on to the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Creating the Key Generator Class &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we have defined our character types, it's time to create the heart of our key generator: the CodeGenerator class. This class will allow us to generate keys based on various parameters such as the type of characters, the number of groups, separators, and more.&lt;/p&gt;

&lt;p&gt;Let's create a &lt;code&gt;index.ts&lt;/code&gt; file in our root folder and import our types, shall we?&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;charactersByType&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;./utils/charactersByType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;characterType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;charType&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;./utils/types/characterType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;separatorType&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;./utils/types/separatorType&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;Now let's write our interface, which will be implemented by our class.&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;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ICodeGenerator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;numberOfCharacters&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;generate&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;string&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;Since we will receive optional parameters as well, let's create a type called &lt;code&gt;Props&lt;/code&gt; and pass the actual properties as optional parameters:&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;export&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;characterType&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;characterType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;groupSeparator&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;separatorType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;numberOfKeys&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;groupFormat&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;string&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;Finally, let's implement those two and create our class.&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CodeGenerator&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ICodeGenerator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;_numberOfCharacters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;_characterType&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;characterType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;_groupSeparator&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;separatorType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;_groups&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;_groupFormat&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;_numberOfKeys&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numberOfCharacters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_numberOfCharacters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numberOfCharacters&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_characterType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;characterType&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;charType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LettersAndNumbers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_groups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;groups&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_groupSeparator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;groupSeparator&lt;/span&gt; &lt;span class="o"&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_numberOfKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;numberOfKeys&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_groupFormat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;groupFormat&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 our &lt;code&gt;constructor&lt;/code&gt;, I assigned a default value for &lt;code&gt;props&lt;/code&gt;, it being an empty object of type &lt;code&gt;Props&lt;/code&gt;. That way, Typescript won't complain about it being the wrong type.&lt;/p&gt;

&lt;p&gt;Also, we had to assign default values to our props in case they are not passed by the user. I've done that using the nullish coalescing operator to ensure that whenever the value is null or undefined, it will be replaced by our default value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Defining and implementing an auxiliary method &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;As you can see in the &lt;code&gt;ICodeGenerator&lt;/code&gt; interface, we'll have a public method called &lt;code&gt;generate&lt;/code&gt; to generate the actual keys.&lt;/p&gt;

&lt;p&gt;However, to make the code inside the method cleaner, we'll have one private method to assist us &lt;strong&gt;validating&lt;/strong&gt; our group format (which can only be used in certain circumstances and need to contain only two types of characters).&lt;/p&gt;

&lt;p&gt;So, let's first write the code for our abstraction, and afterwards the code of the &lt;code&gt;generate&lt;/code&gt; method, which will return an &lt;code&gt;Array&lt;/code&gt; of &lt;code&gt;strings&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  validateGroupFormat method
&lt;/h3&gt;

&lt;p&gt;The role of this private method is to validate the input of the &lt;code&gt;groupFormat&lt;/code&gt; property that can be informed by the user.&lt;/p&gt;

&lt;p&gt;There are 2 rules we need to have in mind for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user can only use the &lt;code&gt;groupFormat&lt;/code&gt; property when the &lt;code&gt;charType&lt;/code&gt; is &lt;code&gt;LettersAndNumbers&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;groupFormat&lt;/code&gt; can only contain the letters "L" (for Letters) and "N" (for Numbers).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, we need to check if the &lt;code&gt;groupFormat&lt;/code&gt; is empty (the user didn't set the property), and if true, skip the entire validation.&lt;/p&gt;

&lt;p&gt;Let's check how this method was implemented. I will split the code into 3 parts for better understanding.&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="kr"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;validateGroupFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;groupFormat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;groupFormat&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="nx"&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;groupFormat is not defined, skipping validation.&lt;/span&gt;&lt;span class="dl"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we've set the method, which will receive the &lt;code&gt;groupFormat&lt;/code&gt; and the &lt;code&gt;characters&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also, our first rule has been set, checking if the &lt;code&gt;groupFormat&lt;/code&gt; is null or undefined. This will output on console a message and skip the validation by returning stopping the method.&lt;/p&gt;

&lt;p&gt;You can suppress this console.log method if you wish. I decided to keep it for debugging purposes.&lt;/p&gt;

&lt;p&gt;Let's continue writing our code. Now we will write the first validation rule.&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;characters&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;charactersByType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Letters&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="k"&gt;new&lt;/span&gt; &lt;span class="nb"&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;The grouptFormat can only be used with 'LettersAndNumbers' charaterType!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will check if the &lt;code&gt;characters&lt;/code&gt; is something other than &lt;code&gt;LettersAndNumbers&lt;/code&gt;. In other words, it checks if &lt;code&gt;characters&lt;/code&gt; is not &lt;code&gt;Letters&lt;/code&gt;, &lt;code&gt;Numbers&lt;/code&gt; or &lt;code&gt;HexChar&lt;/code&gt;, and throw an error if it is.&lt;/p&gt;

&lt;p&gt;Now let's see our second and final rule:&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;regexStatement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;N|L&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/g&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;matchLetters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;groupFormat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regexStatement&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;matchLetters&lt;/span&gt;&lt;span class="o"&gt;!&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="nx"&gt;groupFormat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&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;The group format can only contain letters 'L' and numbers 'N'&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;To check if the &lt;code&gt;groupFormat&lt;/code&gt; contains any letters or characters other than "L" and "N", I created a simple RegEx variable that will be used to verify this rule using the &lt;code&gt;match()&lt;/code&gt; method that exists in every &lt;code&gt;String&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;match&lt;/code&gt; method returns an &lt;code&gt;Array&lt;/code&gt; containing all the characters that match the rule set using RegEx. We stored that array in &lt;code&gt;matchLetters&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Afterwards, we compare the length of &lt;code&gt;matchLetters&lt;/code&gt; with the length of the &lt;code&gt;groupFormat&lt;/code&gt;. If their length are the same, it means all letters are either "L" or "N". If the &lt;code&gt;groupFormat&lt;/code&gt; contains some character other than those, &lt;code&gt;matchLetters&lt;/code&gt;'s length will be smaller than &lt;code&gt;groupFormat&lt;/code&gt;'s length, since the Array will not contain those characters. In this case, we throw an error which will stop our app.&lt;/p&gt;

&lt;p&gt;We are done with this auxiliary method. Now let's dive into the core of our little program: implementing the method for generating the actual keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Defining and implementing our main method &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The good stuff is here.&lt;br&gt;
As before, I will split the code into separate blocks and briefly explain what I did.&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="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&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;characters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;charactersByType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_characterType&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numberOfCharacters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_groupFormat&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_numberOfCharacters&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;CodeGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validateGroupFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_groupFormat&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First I declared and assigned the &lt;code&gt;characters&lt;/code&gt; variable by selecting the characters from inside the &lt;code&gt;charactersByType&lt;/code&gt; object. Note that we used the "non-null assertion operator" to ensure Typescript won't yell at us for passing a parameter that could potentially be &lt;code&gt;undefined&lt;/code&gt; (We know it won't because we have set a default parameter to it).&lt;/p&gt;

&lt;p&gt;Then, a new rule emerges (and you can totally implement this in a different way): if &lt;code&gt;groupFormat&lt;/code&gt; is passed by the user, we will replace the property &lt;code&gt;numberOfCharacters&lt;/code&gt;, which is mandatory, with the length of the &lt;code&gt;groupFormat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's why: Let's say a developer implement this and assign &lt;code&gt;numberOfCharacters&lt;/code&gt; a value of "5", and then pass the &lt;code&gt;groupFormat&lt;/code&gt; a value of "LLNLNLL" (7 characters).&lt;/p&gt;

&lt;p&gt;Without this rule, the &lt;code&gt;generate&lt;/code&gt; method would result a key with 5 characters. However, to ensure the &lt;code&gt;groupFormat&lt;/code&gt; is actually respected and &lt;code&gt;generate&lt;/code&gt; generates a key with 7 characters, I decided to assign to &lt;code&gt;numberOfCharacters&lt;/code&gt; the length of that group, otherwise our loop won't have the necessary number of iterations to return all the characters needed.&lt;/p&gt;

&lt;p&gt;On the other hand, if &lt;code&gt;groupFormat&lt;/code&gt; has less characters than passed in &lt;code&gt;numberOfCharacters&lt;/code&gt;, the problem would have been even worse. Hence the existence of this rule.&lt;/p&gt;

&lt;p&gt;But considering this is a design preference, you can totally omit this rule and instead give priority to &lt;code&gt;numberOfCharacters&lt;/code&gt; as informed in the constructor of the class. However, to do so, you'll need to adapt the code to either not accept a &lt;code&gt;groupFormat&lt;/code&gt; with fewer characters, or define a rule on how the remaining characters would be generated.&lt;/p&gt;

&lt;p&gt;But, let's get back on track. In the next line of code we'll call the &lt;code&gt;validateGroupFormat&lt;/code&gt; method to ensure it has been passed according to our set of rules.&lt;/p&gt;

&lt;p&gt;Next, we will create an Array containing the characters in the &lt;code&gt;groupFormat&lt;/code&gt;, which will be used later, and another Array that will receive our actual generated keys.&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;groupFormatArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_groupFormat&lt;/span&gt;
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_groupFormat&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="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&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;Now we will create 3 nested &lt;code&gt;for&lt;/code&gt; loops, in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The first to iterate on how many keys the user wants to be generated.&lt;/li&gt;
&lt;li&gt;The second will iterate on how many groups that key should have.&lt;/li&gt;
&lt;li&gt;Finally, the last will iterate on how many characters the key will have.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the end of the second &lt;code&gt;for&lt;/code&gt; loop, after our third loop finishes generating our group of keys, we will check if this is the last (or the only) group. If it's not, it will place our &lt;code&gt;groupSeparator&lt;/code&gt; at the end of the characters.&lt;/p&gt;

&lt;p&gt;Inside the last &lt;code&gt;for&lt;/code&gt; loop, we will need to check if &lt;code&gt;groupFormat&lt;/code&gt; was informed, so we can generate the key according to it, and otherwise just generate a key with a random format.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;groupFormat&lt;/code&gt; was informed, we will need to check, in each iteration, if the character generated needs to be a &lt;code&gt;Letter&lt;/code&gt; or a &lt;code&gt;Number&lt;/code&gt;, and reassign &lt;code&gt;characters&lt;/code&gt; accordingly.&lt;/p&gt;

&lt;p&gt;Next, to generate the character, we will randomly select a number between 0 and the length of &lt;code&gt;characters&lt;/code&gt; (using &lt;code&gt;Math.random&lt;/code&gt; and &lt;code&gt;Math.floor&lt;/code&gt;), and use that number as an index for selecting a character inside &lt;code&gt;characters&lt;/code&gt;, using the &lt;code&gt;charAt&lt;/code&gt; method of Strings.&lt;/p&gt;

&lt;p&gt;Finally, we will finalize the code by returning the keys.&lt;/p&gt;

&lt;p&gt;Let's see how this was done:&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;for&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;count&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="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_numberOfKeys&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;count&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="kd"&gt;let&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;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&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;groups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;groups&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_groups&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;groups&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="k"&gt;for&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;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;numberOfCharacters&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_groupFormat&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;char&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;groupFormatArr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

          &lt;span class="nx"&gt;characters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;L&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;characters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;charactersByType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;charType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Letters&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="nx"&gt;characters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;charactersByType&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;charType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Numbers&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;characters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_groups&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;groups&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="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_groupSeparator&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="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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;keys&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the end of our code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Step: Generating Keys &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Now let's execute it inside another file:&lt;/p&gt;

&lt;p&gt;I created a new file called &lt;code&gt;test.js&lt;/code&gt; that will import our class, set the props, create a new instance of the class and, finally, generate our keys.&lt;/p&gt;

&lt;p&gt;Let's see how it works:&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;KeyGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./dist/index.js&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;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;characterType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LettersAndNumbers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;groupSeparator&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="na"&gt;numberOfKeys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;groupFormat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;LLLNN&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;codeGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;KeyGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&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;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;codeGenerator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here I wanted to create 5 keys containing 3 groups each. Each group will have the following format: "LLLNN", where "L" stands for "Letter" and "N" for "Number", as we saw earlier.&lt;/p&gt;

&lt;p&gt;I did not inform the &lt;code&gt;groupSeparator&lt;/code&gt;, so the default is going to be used.&lt;/p&gt;

&lt;p&gt;Notice I instantiated the class with the number 4, meaning I informed I wanted a key containing 4 characters, but I also informed a &lt;code&gt;groupFormat&lt;/code&gt; of 5 characters.&lt;/p&gt;

&lt;p&gt;Finally, I logged created another variable to receive the result of the &lt;code&gt;generate&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Notice you can also instantiate and generate the keys in a single line, like this:&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;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;KeyGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running this code, I got this:&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="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;STQ28-LYK19-AFK35&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;JWK56-DLO89-QUO83&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;NBC89-FAM05-LFO68&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;XBS08-ZAX06-TOT61&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;RUW52-KHC73-BVC16&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;Observe how we received the right amount of keys with 3 groups each, but each group has 5 characters instead of 4. This is due to our rule that the length of &lt;code&gt;groupFormat&lt;/code&gt; will have priority over the &lt;code&gt;numberOfCharacters&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Well, that's it for today. &lt;/p&gt;

&lt;p&gt;The full and updated code can be seen here: &lt;a href="https://github.com/joaotextor/easy-key-generator"&gt;https://github.com/joaotextor/easy-key-generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know your thoughts about my first post here on dev.to in the comment section. Was I clear enough? Are there any adjustments you might do in my code?&lt;/p&gt;

&lt;p&gt;I hope to get back here soon with more content for y'all.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
