<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Luca Del Puppo — Run, Code &amp; Learn</title><description>Google Developer Expert in Web Technologies, GitKraken Ambassador, Codemotion Ambassador, and AI Native Engineer at Nearform.</description><link>https://delpuppo.net/</link><item><title>Automating my Codemotion Badge with Antigravity</title><link>https://delpuppo.net/blog/automating-my-codemotion-badge-with-antigravity/</link><guid isPermaLink="true">https://delpuppo.net/blog/automating-my-codemotion-badge-with-antigravity/</guid><description>Today, I wanna show you how to set up your devices with Antigravity using only the agentic mode,...</description><pubDate>Wed, 08 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today, I wanna show you how to set up your devices with Antigravity using only the agentic mode, without touching any code.&lt;/p&gt;
&lt;p&gt;At the last CodeMotion Rome, I got my special badge. A &lt;a href=&quot;https://www.cmnode.it/en/&quot;&gt;CM Node&lt;/a&gt;, a special hardware board, that you can customise for your conferences.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I&apos;m not a super nerd for this kind of stuff, so I decided to use Antigravity and all its capabilities to build and flash the best board ever for my future conferences.&lt;/p&gt;
&lt;h2&gt;Small intro about the board&lt;/h2&gt;
&lt;p&gt;This board has been delivered with a &lt;a href=&quot;https://github.com/Codemotion-Official/CMNode&quot;&gt;GitHub repository&lt;/a&gt; to understand how to flash it and how it works. In Rome, I saw different attendees with awesome badges. For instance, Soumaya had built a badge with a small plastic hand that used a sensor when someone was near her; it started waving to say hi.&lt;br /&gt;
Since that day, I have been thinking about what I can build to have a cool badge. Nothing has come to my mind, so today, with this blog, we will build my badge together, and thanks to Antigravity, we will create the best version possible.&lt;/p&gt;
&lt;h2&gt;Antigravity&lt;/h2&gt;
&lt;p&gt;If you don&apos;t know &lt;a href=&quot;https://antigravity.google/&quot;&gt;Antigravity&lt;/a&gt;. Antigravity is a set of tools built by Google. We have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://antigravity.google/product/antigravity-2&quot;&gt;Antigravity 2.0&lt;/a&gt;: is a dedicated platform to work with agents. Orchestrate multiple autonomous agents working in parallel across independent projects.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://antigravity.google/product/antigravity-cli&quot;&gt;Antigravity CLI&lt;/a&gt;: terminal-first surface to interact with Antigravity agents. Stay in your flow without context switching&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://antigravity.google/product/antigravity-ide&quot;&gt;Antigravity IDE&lt;/a&gt;: editor view offers tab autocompletion, natural language code commands, and a configurable, and context-aware configurable agent&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://antigravity.google/product/antigravity-sdk&quot;&gt;Antigravity SDK&lt;/a&gt;: build AI agents that autonomously read files, run commands, edit code, and more. The Agent SDK gives you the same tools, agent loop, and context management that power Google Antigravity, programmable in Python.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Today, in this blog post, we will use Antigravity 2.0 to set up the board. You can use this tool to orchestrate many projects from a unique UI. This tool is fully agentic; using natural language, you can spawn agents, plan, and work on your projects. If you want to check the codebase in detail, you must use the Antigravity IDE. I’m not a fan of this decision, I’d prefer one tool for both, but this is what we have, and we must use it as it is.&lt;/p&gt;
&lt;h3&gt;Let’s start cooking&lt;/h3&gt;
&lt;p&gt;Okay, after this introduction, let’s see what we can do with Antigravity and the CodeMotion Board.&lt;/p&gt;
&lt;p&gt;So, I’m dumb about this board right now, and I want to use Antigravity to figure out what I can do with it and get an idea of what my badge might look like.&lt;/p&gt;
&lt;p&gt;I open the Antigravity app, and from the UI, I start a new project, and in the prompt, I type&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I want to set up my Codemotion Badge.&lt;br /&gt;
It&apos;s a CMNode v0 &lt;a href=&quot;https://www.cmnode.it/en/&quot;&gt;https://www.cmnode.it/en/&lt;/a&gt;, and it can be programmed.&lt;br /&gt;
I want to create two different screens: the first a classic one with name, surname, heading, and company, and a QR code linking to my website.&lt;br /&gt;
The second one must be fantastic, and I want different options to choose from you.&lt;/p&gt;
&lt;p&gt;I have this repository as an example to set up the badge &lt;a href=&quot;https://github.com/Codemotion-Official/CMNode&quot;&gt;https://github.com/Codemotion-Official/CMNode&lt;/a&gt;; you can use it as an example to create my badge.&lt;br /&gt;
Lastly, I don&apos;t want to flash the ROM every time, so I&apos;d like a small web page I can access via Wi-Fi to update the information.&lt;/p&gt;
&lt;p&gt;Can you plan the work to do it?&lt;br /&gt;
Include also two or three possible ideas for the second screen. It must be cool and fancy!&lt;/p&gt;
&lt;p&gt;The badge is already connected to the laptop in case you want to deploy the result.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, I press enter and let’s see the result and what it will cook.&lt;/p&gt;
&lt;p&gt;The result&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1&gt;&lt;strong&gt;CMNode v0 WiFi Configuration &amp;amp; Dual Screen Setup&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;The goal of this task is to upgrade your CMNode v0 badge by replacing the serial-based configuration with a Wi-Fi-based web interface. We will also save the configured data to flash memory so it persists across reboots, and implement two different display layouts: a &quot;Classic&quot; screen and a &quot;Fantastic&quot; screen.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;User Review Required&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Please review the proposed ideas for the &quot;Fantastic&quot; screen below. Let me know which one you prefer, or if you&apos;d like to combine elements from different ideas!&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Ideas for the &quot;Fantastic&quot; Second Screen:&lt;/strong&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The &quot;Hacker Terminal&quot;&lt;/strong&gt; : A retro command-line interface aesthetic. The screen features a black background with white text, simulating a terminal session (e.g., &lt;code&gt;&amp;gt; user@cmnode:~$ whoami&lt;/code&gt;, followed by your details). We can use monospace fonts and add some faux hex-dumps or ASCII elements.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The &quot;RPG Stats / Gamer Card&quot;&lt;/strong&gt; : Your badge becomes a character stat sheet. It will display you as a &quot;Level 99 Developer&quot; with stats like &quot;INT: 99&quot;, &quot;COFFEE: 100%&quot;, an energy bar, and your details integrated into a game-like UI.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The &quot;Minimalist Cyberpunk&quot;&lt;/strong&gt; : A bold, modern, and high-contrast design. It uses large vertical typography for your name, heavy geometric shapes, thick red accent lines, and a large barcode aesthetic alongside your QR code.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Let me know which of these three ideas (or a mix!) you want me to build for the second screen.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Proposed Changes&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;We will modify the firmware to support a captive-like Wi-Fi Access Point and Web Server.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Core Logic Updates&lt;/strong&gt;&lt;/h3&gt;
&lt;h4&gt;&lt;strong&gt;[MODIFY]&lt;/strong&gt; &lt;code&gt;src/main.cpp&lt;/code&gt; &lt;strong&gt;(or&lt;/strong&gt; &lt;code&gt;NodeV0.ino&lt;/code&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wi-Fi Access Point&lt;/strong&gt; : The ESP32-C3 will broadcast an SSID (e.g., &lt;code&gt;CMNode-Config&lt;/code&gt;). You can connect to it with your phone or laptop.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Web Server&lt;/strong&gt; : A built-in web server will serve a simple, mobile-friendly HTML configuration page at &lt;a href=&quot;http://192.168.4.1&quot;&gt;&lt;code&gt;http://192.168.4.1&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Form Submission&lt;/strong&gt; : The webpage will contain a form to update your Name, Surname, Role, Company, QR Link, and a dropdown to select the active screen layout (Classic vs Fantastic).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Persistent Storage&lt;/strong&gt; : Integrate the &lt;code&gt;Preferences&lt;/code&gt; library to save your data to the ESP32&apos;s non-volatile storage (NVS). This ensures your badge remembers your details even after turning off.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Display Pipeline&lt;/strong&gt; : Refactor the &lt;code&gt;drawContent()&lt;/code&gt; function to support rendering two completely different layouts based on your selection.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;Verification Plan&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Manual Verification&lt;/strong&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I will write the updated code and you will flash it to your badge via PlatformIO or Arduino IDE.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We will verify that the badge broadcasts the &lt;code&gt;CMNode-Config&lt;/code&gt; Wi-Fi network.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We will connect to it, open the web page, submit new data, and verify that the E-paper display updates immediately.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We will reboot the badge to confirm the data is preserved.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We will toggle between the Classic and Fantastic screens to verify the layouts.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;I commented on the plan, deciding to go with option one and asked for an example design.&lt;br /&gt;
Antigravity has started reviewing the plan and updated it in this way&lt;/p&gt;
&lt;blockquote&gt;
&lt;h1&gt;&lt;strong&gt;CMNode v0 WiFi Configuration &amp;amp; Dual Screen Setup&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;The goal of this task is to upgrade your CMNode v0 badge by replacing the serial-based configuration with a Wi-Fi-based web interface. We will also save the configured data to flash memory so it persists across reboots, and implement two different display layouts: a &quot;Classic&quot; screen and a &quot;Fantastic&quot; screen.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Design Choice: &quot;Hacker Terminal&quot;&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;You&apos;ve selected the &lt;strong&gt;Hacker Terminal&lt;/strong&gt; idea for the second screen. This layout will simulate a retro command-line interface on the E-ink display:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Background&lt;/strong&gt; : Black (inverted).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Text&lt;/strong&gt; : Monospace white font, simulating terminal output (&lt;code&gt;root@cmnode:~$ whoami&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data&lt;/strong&gt; : Your name, surname, role, and company will be displayed as the &quot;output&quot; of the terminal command.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Accents&lt;/strong&gt; : Faux hex-dumps or system logs on the side, and a right-aligned QR code.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here is a mockup of the design:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Does this mockup and the updated plan look good to you? If so, I will proceed with the implementation!&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Proposed Changes&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;We will modify the firmware to support a captive-like Wi-Fi Access Point and Web Server.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Core Logic Updates&lt;/strong&gt;&lt;/h3&gt;
&lt;h4&gt;&lt;strong&gt;[MODIFY]&lt;/strong&gt; &lt;code&gt;src/main.cpp&lt;/code&gt; &lt;strong&gt;(or&lt;/strong&gt; &lt;code&gt;NodeV0.ino&lt;/code&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Wi-Fi Access Point&lt;/strong&gt; : The ESP32-C3 will broadcast an SSID (e.g., &lt;code&gt;CMNode-Config&lt;/code&gt;). You can connect to it with your phone or laptop.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Web Server&lt;/strong&gt; : A built-in web server will serve a simple, mobile-friendly HTML configuration page at &lt;a href=&quot;http://192.168.4.1&quot;&gt;&lt;code&gt;http://192.168.4.1&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Form Submission&lt;/strong&gt; : The webpage will contain a form to update your Name, Surname, Role, Company, QR Link, and a dropdown to select the active screen layout (Classic vs Fantastic).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Persistent Storage&lt;/strong&gt; : Integrate the &lt;code&gt;Preferences&lt;/code&gt; library to save your data to the ESP32&apos;s non-volatile storage (NVS). This ensures your badge remembers your details even after turning off.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Display Pipeline&lt;/strong&gt; : Refactor the &lt;code&gt;drawContent()&lt;/code&gt; function to support rendering two completely different layouts based on your selection.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;strong&gt;Verification Plan&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Manual Verification&lt;/strong&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I will write the updated code and you will flash it to your badge via PlatformIO or Arduino IDE.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We will verify that the badge broadcasts the &lt;code&gt;CMNode-Config&lt;/code&gt; Wi-Fi network.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We will connect to it, open the web page, submit new data, and verify that the E-paper display updates immediately.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We will reboot the badge to confirm the data is preserved.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We will toggle between the Classic and Fantastic screens to verify the layouts.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;As you can see, we now have a clear idea of how the second screen should look and a plan to implement everything, but before spawning the agent work, I&apos;d also like to have a design of the first screen of the badge, so using the chat, I ask to include it also in the plan.&lt;br /&gt;
After two iterations of the prompt, this is the result&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;The implementation&lt;/h3&gt;
&lt;p&gt;To implement the plan, we just need to press the Proceed button and wait&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;During the implementation, we can check what is happening through the UI&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;And if we notice something weird, we can stop the agent and type a new prompt to drive it again on the right path.&lt;br /&gt;
If you, like me, prefer to get confirmation before running commands or editing files, you must also approve these actions through the UI.&lt;/p&gt;
&lt;p&gt;After 2 minutes, this is the result.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;And if I connect my laptop to the badge Wi-Fi, I can configure my badge.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;The refine&lt;/h3&gt;
&lt;p&gt;Now we have a badge working, but we want to improve it a bit: first, I want to change the screen by pressing the button on the back without connecting to the badge&apos;s Wi-Fi, and I want to set the Wi-Fi password via Environment Variables.&lt;br /&gt;
So I can prompt this&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Can we also change the screen view using the button on the rear of the badge without connecting to the badge&apos;s Wi-Fi?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And after a minute, the result is ready, and my badge has been flashed.&lt;br /&gt;
And lastly, I can ask not to hard-code the password but use an environment variable,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;use an environment variable for the wifi password&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;same here, after one minute and a couple of approvals, the result is again ready and in my badge.&lt;/p&gt;
&lt;p&gt;To complete, I want to change the layout by using one of the buttons on the back of the badge. So again I ask Antigravity to do it for me.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Can we change the screen view also by using the button in the rear of the badge without connecting to the badge wifi?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and same here, after some minutes, sometimes the result is happier in the badge.&lt;/p&gt;
&lt;p&gt;And the final result is this one&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;and this one&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;It&apos;s time to wrap up!&lt;br /&gt;
So my experience with Antigravity has been great! I love to use it to build new things, or as a teammate to learn new technology, or just to prototype a pet project like this one.&lt;/p&gt;
&lt;p&gt;If you are in the agentic development, this tool can be a good one for you!&lt;br /&gt;
The experience is great, and if you want to have control over different projects or streams, it can be really helpful. The only pain point for me is the fact that if you want to check the code, you must install another tool, the Antigravity IDE, to check it.&lt;/p&gt;
&lt;p&gt;In this era of agent development, what I find great is the ability to plan and review the changes before the agent implements them! This is the game-changer for me in this moment, and then a lot and a lot of code review!&lt;/p&gt;
&lt;p&gt;Okay, that&apos;s it! I hope you enjoy this introduction to Antigravity and that you now want to test it for your project.&lt;/p&gt;
&lt;p&gt;I hope you also like my new super badge 🚀&lt;/p&gt;
&lt;p&gt;&lt;em&gt;p.s. to check the code result, you can navigate to this&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/codemotion-badge&quot;&gt;&lt;em&gt;repository&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Google Cloud credits are provided for this project.&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>agenticarchitect</category><category>googleantigravity</category></item><item><title>Take control of your job with GitLens Launchpad</title><link>https://delpuppo.net/blog/take-control-of-your-job-with-gitlens-launchpad/</link><guid isPermaLink="true">https://delpuppo.net/blog/take-control-of-your-job-with-gitlens-launchpad/</guid><description>As a developer, you have to take control of your projects every day. Whether it is a company...</description><pubDate>Tue, 23 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As a developer, you have to take control of your projects every day. Whether it is a company repository, an open source project you maintain or collaborate on, or a simple pet project.&lt;/p&gt;
&lt;p&gt;Gaining control over your projects often depends on the platform you&apos;re working with. While there are many options available, such as &lt;a href=&quot;http://atlassian.com/&quot;&gt;Atlassian&lt;/a&gt; and &lt;a href=&quot;https://gitlab.com&quot;&gt;GitLab&lt;/a&gt;, today I will focus on using &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; as the platform of choice. Let me guide you through how you can effectively manage your projects on &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ll talk about the &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; one because that is where I’m working on.&lt;/p&gt;
&lt;p&gt;For me, checking the status of my PRs is essential in my daily work. On average, I spend about one or two hours a day tracking down failing CI checks and keeping my PRs in sync with the main branch, or reviewing other PRs.&lt;/p&gt;
&lt;p&gt;To do that, I used to use the &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; website on &lt;a href=&quot;https://github.com/pulls&quot;&gt;my PRs page&lt;/a&gt;. This page is good; you can find all your PRs, including those where your teammates are requesting a review. You can check whether your PR has reviews and whether the CI passes.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Here you can see my PRs at this specific moment.&lt;/p&gt;
&lt;p&gt;As you can see, you can immediately receive information about the PRs, the number of comments, and more.&lt;/p&gt;
&lt;p&gt;I used this page for a while because it is a perfect way to check all the work across many repositories, but it has a small problem: to check the page, I have to switch between &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VSCode&lt;/a&gt; and the browser during my job. This constant switching might seem trivial, but research suggests it takes an average of 23 seconds to return to a productive state after such a context switch. In the fast-paced developer environment, these seconds add up, potentially impacting overall efficiency and output.&lt;/p&gt;
&lt;p&gt;So, I decided to search for another solution that would let me have the same information across the projects without leaving my &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VSCode&lt;/a&gt; instance.&lt;/p&gt;
&lt;h2&gt;The first useful extensions to the migration&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github&quot;&gt;GitHub Pull Requests&lt;/a&gt; was the first extension I started to test. This extension enables checking all PRs in the current repository I’m working on. I can see my open PRs and my teammates&apos; open PRs. From a &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VSCode&lt;/a&gt; panel, I can check the status of a PR or review another one.&lt;br /&gt;
This extension enables us to open a PR directly from &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VSCode&lt;/a&gt; without using the &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; website, reducing the need to switch context between the editor and the &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; website.&lt;br /&gt;
Here is a picture of the extension&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;As you can see, in the left panel, we can control PRs and Issues. By clicking the PR, we can view its home page. By clicking the arrow icon that appears when you hover over the PR, you can go to the Review mode and add comments or suggestions to that PR.&lt;/p&gt;
&lt;p&gt;That extension has improved my DX experience, especially in PR creation and review, but, as you can see, it works only on the open repository, which is a limitation, since I cannot see if in other projects something or someone is blocked by my work, or it’s waiting for a review or something else.&lt;/p&gt;
&lt;h2&gt;The Final Solution&lt;/h2&gt;
&lt;p&gt;While browsing the web, I came across a feature of &lt;a href=&quot;https://www.gitkraken.com/&quot;&gt;GitKraken&lt;/a&gt; called &lt;a href=&quot;https://www.gitkraken.com/features/launchpad&quot;&gt;Launchpad&lt;/a&gt;. This feature enables us to get a big-picture view of all issues and PRs where we are the creator or a follower. If you don’t know &lt;a href=&quot;https://www.gitkraken.com/&quot;&gt;GitKraken&lt;/a&gt;, it is a Git client with an awesome UI for managing your repositories. You can use it as a &lt;a href=&quot;https://www.gitkraken.com/git-client?_gl=1*1yb8ynx*_up*MQ..*_ga*MTM4MjU2MTEwMS4xNzY2MjM2Mjc3*_ga_TTGBQHQ5E4*czE3NjYyMzYyNzYkbzEkZzAkdDE3NjYyMzYyNzYkajYwJGwxJGgxNjcyOTAyNTQ3&quot;&gt;desktop app&lt;/a&gt;, &lt;a href=&quot;https://gitkraken.dev/&quot;&gt;website&lt;/a&gt;, editor extension (&lt;a href=&quot;https://www.gitkraken.com/gitlens?_gl=1*w5a9a6*_up*MQ..*_ga*MTEyMDYwODM3LjE3NjYyMzYzMTQ.*_ga_TTGBQHQ5E4*czE3NjYyMzYzMTMkbzEkZzAkdDE3NjYyMzYzMTMkajYwJGwxJGgyMDQ0NjUzMjY0&quot;&gt;GitLens&lt;/a&gt;), or the &lt;a href=&quot;https://www.gitkraken.com/cli?_gl=1*1ltt9q5*_up*MQ..*_ga*MTEyMDYwODM3LjE3NjYyMzYzMTQ.*_ga_TTGBQHQ5E4*czE3NjYyMzYzMTMkbzEkZzEkdDE3NjYyMzY2ODgkajYwJGwxJGgyMDQ0NjUzMjY0&quot;&gt;CLI&lt;/a&gt;. They have also released an &lt;a href=&quot;https://www.gitkraken.com/mcp?_gl=1*1p7bqfc*_up*MQ..*_ga*MTEyMDYwODM3LjE3NjYyMzYzMTQ.*_ga_TTGBQHQ5E4*czE3NjYyMzYzMTMkbzEkZzEkdDE3NjYyMzY3MjAkajI4JGwxJGgyMDQ0NjUzMjY0&quot;&gt;MCP server&lt;/a&gt; in the last period to manage your repository through an LLM.&lt;br /&gt;
As you can imagine, I use the &lt;a href=&quot;https://www.gitkraken.com/gitlens&quot;&gt;GitLens&lt;/a&gt; extension, which has a panel that lets me see everything across my repositories.&lt;br /&gt;
&lt;em&gt;Spoiler: I use it with&lt;/em&gt; &lt;a href=&quot;https://github.com/&quot;&gt;&lt;em&gt;GitHub&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, but you can also use it with&lt;/em&gt; &lt;a href=&quot;https://bitbucket.org/&quot;&gt;&lt;em&gt;Bitbucket&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://gitlab.com/&quot;&gt;&lt;em&gt;GitLab&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. It can also combine data across different platforms.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In this panel, there are different groups where you can find your PRs that meet that status. If you click the PR, you will see a pop-up that lets you get more info or jump into the repository if you have already set it up on your machine.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;As you can see, just using these two extensions, I reduced the number of switches between my lovely &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VSCode&lt;/a&gt; and the &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; website. In my editor, I already have control over all my repositories, and with the correct panel, I can do most of my work directly in the editor.&lt;/p&gt;
&lt;p&gt;Before closing, I’d like to give you another extension that reduces the need to switch between the editor and the &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; website. This extension is the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-github-actions&quot;&gt;GitHub Actions&lt;/a&gt; one. This extension lets you check the status of actions directly in the editor, without jumping to &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; to search for them.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;It’s time to wrap up this article.&lt;br /&gt;
At first, I showed how I used to check my current work across projects on &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt;, but eventually it became a pain point because switching between the editor and the browser was annoying.&lt;br /&gt;
Then I moved to the &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github&quot;&gt;GitHub Pull Requests&lt;/a&gt; extension, which enables me to open, review, and check PRs and Issues in the current open repository.&lt;br /&gt;
Lastly, I talked about the &lt;a href=&quot;https://www.gitkraken.com/gitlens&quot;&gt;GitLens&lt;/a&gt; &lt;a href=&quot;https://www.gitkraken.com/features/launchpad&quot;&gt;Launchpad,&lt;/a&gt; which, through a panel in the editor, provides a big-picture view of all the PRs across the repositories I’m working on and helps me reduce switching between the editor and &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; during my daily work.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you want to use the&lt;/em&gt; &lt;a href=&quot;https://www.gitkraken.com/gitlens&quot;&gt;&lt;em&gt;GitLens&lt;/em&gt;&lt;/a&gt; &lt;em&gt;Launchpad, it is a PRO feature that requires a valid&lt;/em&gt; &lt;a href=&quot;https://www.gitkraken.com/&quot;&gt;&lt;em&gt;GitKraken&lt;/em&gt;&lt;/a&gt; &lt;em&gt;license. To buy one, check this&lt;/em&gt; &lt;a href=&quot;https://gitkraken.cello.so/I4dkhuQcpJN&quot;&gt;in this reference&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That’s it for this article. I hope this feature can also improve your daily DX, and see you in the following articles.&lt;/p&gt;
&lt;p&gt;Bye bye 👋&lt;/p&gt;
</content:encoded><category>gitkraken</category><category>tooling</category><category>Developer Tools</category><category>DeveloperExperience</category></item><item><title>The Mood Mirror App - My Antigravity first experience</title><link>https://delpuppo.net/blog/the-mood-mirror-app/</link><guid isPermaLink="true">https://delpuppo.net/blog/the-mood-mirror-app/</guid><description>Just a week ago, Google launched Antigravity, and why not give it a try and share my experience? And...</description><pubDate>Thu, 04 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Just a week ago, Google launched &lt;a href=&quot;https://antigravity.google/&quot;&gt;Antigravity&lt;/a&gt;, and why not give it a try and share my experience? And here I am for this.&lt;/p&gt;
&lt;p&gt;In this article, I&apos;ll talk about my first experience with Antigravity and how I built a small web app called &lt;strong&gt;The Mood Mirror&lt;/strong&gt;. This app emulates an artist who can convert your mood into abstract images or videos.&lt;/p&gt;
&lt;p&gt;Spoiler: this app uses &lt;a href=&quot;https://deepmind.google/models/gemini/&quot;&gt;Gemini 3&lt;/a&gt;, &lt;a href=&quot;https://gemini.google/overview/image-generation/&quot;&gt;Nano Banana Pro&lt;/a&gt; and &lt;a href=&quot;https://gemini.google/overview/video-generation/&quot;&gt;Veo&lt;/a&gt;, but I&apos;ll talk about them in a future article.&lt;/p&gt;
&lt;h2&gt;Antigravity Intro&lt;/h2&gt;
&lt;p&gt;Let&apos;s start with a small presentation about Antigravity.&lt;/p&gt;
&lt;p&gt;Google Antigravity is an Agentic IDE. It is a fork of VSCode with a dedicated agent section that features models such as Gemini, Claude, and GPT.&lt;/p&gt;
&lt;p&gt;This last part is what makes Antigravity different from VSCode or Cursor; this section is built and maintained by Google. Yes, the experiences are common, but how this Agent section is integrated into the IDE is what differentiates it from the others, and this is where all the IDE teams are working to improve their users&apos; DX.&lt;/p&gt;
&lt;p&gt;For more info about Google Antigravity, you can check its website &lt;a href=&quot;https://antigravity.google/&quot;&gt;in this reference&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&quot;The Mood Mirror&quot; Setup&lt;/h2&gt;
&lt;p&gt;To test the tool&apos;s full power, I decided to build the application almost entirely in &quot;Vibe Coding&quot;. To that end, I began by setting up the project and wrote a prompt outlining my intention and what I hoped to achieve.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In this picture, you can see what Antigravity looks like, and as you can imagine, in the chat, you can prompt our intention.&lt;/p&gt;
&lt;p&gt;For my application, I entered this prompt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; You are a Senior Software Engineer Agent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Project:&lt;/strong&gt; Build a responsive web application called &lt;strong&gt;&quot;Mood Mirror&quot;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stack:&lt;/strong&gt; React, Tailwind CSS, and the Gemini 3 SDK.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Core Functionality:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; Create a clean, minimalist text area where the user enters how they feel (e.g., &quot;I am anxious about my deadline&quot;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The &quot;Director&quot; Logic (Gemini 3):&lt;/strong&gt; When the user submits, send the text to Gemini 3.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Analyse the &lt;strong&gt;Sentiment Score&lt;/strong&gt; (0 to +1.0).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Extract an &lt;strong&gt;Emotional Colour Palette&lt;/strong&gt; (e.g., &quot;Stormy Grey and Electric Blue&quot;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generate a &lt;strong&gt;Creative Prompt&lt;/strong&gt; for an abstract art piece based on that emotion.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The &quot;Artist&quot; Execution (Nano Banana):&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Pass the &lt;em&gt;Creative Prompt&lt;/em&gt; to the Nano Banana Pro API.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Conditional Logic:&lt;/strong&gt; If the Sentiment Score is extreme (above 0.8 or below -0.8), request a &lt;strong&gt;5-second looping Video (MP4)&lt;/strong&gt;. Otherwise, request a &lt;strong&gt;High-Res Image (PNG)&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Dynamic UI:&lt;/strong&gt; Update the app&apos;s background gradient instantly to match the &lt;em&gt;Emotional Colour Palette&lt;/em&gt; returned by Gemini while the image generates.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Execution Plan:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Scaffold the project.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write the SentimentService using the Gemini 3 logic.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Implement the Nano Banana API hook.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Deploy to preview.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The result of this prompt was a plan of action for Antigravity to implement my request. I got this result because I selected &quot;planning&quot; in the bottom-left drop-down. If you decide to go with the fast option, Antigravity doesn&apos;t show the plan and immediately develops it.&lt;/p&gt;
&lt;p&gt;Btw, I chose the planning options so that I can check and comment on this plan directly in the IDE.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In the image above, you can see an example of the plan I received. As you can see, you can either accept it or review it, and then ask Antigravity to check your comments and review the plan.&lt;/p&gt;
&lt;p&gt;The prompt and its plan are the result of this &lt;a href=&quot;https://github.com/Puppo/the-mood-mirror/commit/e5a2784b77c93014a9cb36ecd70c94a2ef8e4a13&quot;&gt;commit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What went wrong? 😑&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The setup has gone smoothly and pretty well, but I ran into an issue: Antigravity generated a JavaScript application rather than a TypeScript one. Not a big deal. Later, I asked it to review the project in JavaScript and TypeScript, and it converted it without any issues. &lt;a href=&quot;https://github.com/Puppo/the-mood-mirror/commit/66ba677e104cca6c1c09de4d339e1e6e9cae4c77&quot;&gt;in the GitHub repository&lt;/a&gt; you can see the result.&lt;br /&gt;
And lastly, it generated two files, one for the Sentiment discovery and the other for the image generation, but it created a sort of mock service without.&lt;br /&gt;
I didn’t iterate again to fix them, but I’ve worked on them later.&lt;/p&gt;
&lt;h2&gt;Commit linting into the project&lt;/h2&gt;
&lt;p&gt;The second test I did was about setting up a development tool to verify the commit messages. I like to use commitlint and conventional commits for my project, so my second test was adding the setup for these tools.&lt;br /&gt;
I opened a new chat, and I entered this prompt.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I want to add commitlint and conventional-commit to this project. Can you set it up?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I was concerned that the prompt wasn’t particular, but I did it to see what Antigravity produces and how good the results are.&lt;/p&gt;
&lt;p&gt;I ran that prompt in “fast” mode, and the first result was pretty good. It installs and sets up &lt;code&gt;@commitlint/cli&lt;/code&gt; and &lt;code&gt;@commitlint/config-conventional&lt;/code&gt; and after that, it added &lt;code&gt;husky&lt;/code&gt; to validate the commit message in the pre-commit hook. I’m not a &lt;code&gt;husky&lt;/code&gt; fan, I prefer &lt;code&gt;lefthook&lt;/code&gt;. So after this first iteration, I asked Antigravity to replace &lt;code&gt;husky&lt;/code&gt; with &lt;code&gt;lefthook&lt;/code&gt;. The result I got worked, but it wasn’t the best solution ever. I decided not to reiterate this time, to leave it in the repo and also show what an Agentic IDE can generate when we don’t check its results and trust it too much.&lt;/p&gt;
&lt;p&gt;In this second iteration, Antigravity added lefthook without any problem, but it didn’t remove all the &lt;code&gt;husky&lt;/code&gt; references. In fact, if you check the &lt;a href=&quot;https://github.com/Puppo/the-mood-mirror/commit/1ca9fed538fa1ee15f3e8dd07ac149e01ee68bf3&quot;&gt;commit&lt;/a&gt;, you can see the &lt;code&gt;_husky&lt;/code&gt; folder with two files, with no sense script for this repo, and in the &lt;code&gt;package.json&lt;/code&gt;, it forgot to remove the &lt;code&gt;prepare&lt;/code&gt; script.&lt;/p&gt;
&lt;p&gt;As you can see, our code review when using these tools is crucial to avoid trash or unnecessary code.&lt;/p&gt;
&lt;h2&gt;The Gemini 3.0 integration&lt;/h2&gt;
&lt;p&gt;The next test was the Gemini integration to build the Sentiment analysis service.&lt;br /&gt;
As I did in the previous tests, I started from a new chat.&lt;br /&gt;
The prompt in this case was a bit more articulated. I asked to generate a service that accepts a text and, through Gemini, returns a structured result with these fields:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;moodScore&lt;/em&gt;: a value between 0 and 1 to determine the mood score&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;promptType&lt;/em&gt;: This is the value that determines if the mirror will show an image or a video&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;promptText&lt;/em&gt;: This is the text to pass later to generate the video or the image&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This result must later be used to generate an image or a video using NanoBanana Pro or Veo 3.&lt;/p&gt;
&lt;p&gt;This iteration has been a bit convoluted. The first version used the old npm package &lt;code&gt;@google/generative-ai&lt;/code&gt; and not the new one &lt;code&gt;@google/genai&lt;/code&gt;. So I kept reiterating to get the code updated to the new version of the SDK. Another issue I had was that Antigravity created a single file to handle both images and videos. So, for that, I reiterated the need to split the logic for image and video generation into two separate files, and I also fixed the video generation to use the video model instead of the image model.&lt;/p&gt;
&lt;p&gt;After that, I got a working application that met my first requirements, and you can see a demo in the video below. &lt;em&gt;[and&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/the-mood-mirror/commit/9dc0d5f74ee505ecf3f04f7baa53248eeea0e331#diff-053150b640a7ce75eff69d1a22cae7f0f94ad64ce9a855db544dda0929316519&quot;&gt;in the GitHub repository&lt;/a&gt; &lt;em&gt;you can check the commit]&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=098qvXvpVZQ&quot;&gt;https://www.youtube.com/watch?v=098qvXvpVZQ&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;It’s time to wrap up this first experience with Antigravity.&lt;/p&gt;
&lt;p&gt;Overall, the experience with the tool was good. This is its first version, and only a few weeks after its release, Antigravity showed great DX and a good understanding of what I want to achieve.&lt;/p&gt;
&lt;p&gt;Yes, it is not perfect, and in some cases, the plan described at the beginning hasn’t been satisfied. But this also happens with IDEs that have been in place for months.&lt;/p&gt;
&lt;p&gt;As with the other Agentic IDEs, including Antigravity, developer checks are key to boosting implementation velocity while maintaining codebase quality.&lt;/p&gt;
&lt;p&gt;The planning mode is fantastic in my opinion, because taking a look at the plan and reviewing or confirming it before starting the implementation can reduce the time wasted on reiterating the Agent result; as we saw, it’s still not perfect yet, but I’m pretty sure it will be tuned and improved in the future.&lt;/p&gt;
&lt;p&gt;If I had to rate this first experience, I&apos;d give it &lt;strong&gt;7/10&lt;/strong&gt; because the flow was excellent, but I expected more precise results.&lt;/p&gt;
&lt;p&gt;Okay, that’s all. I hope you enjoyed this article. Let me know in the comments your experience with Antigravity or other Agentic IDEs.&lt;/p&gt;
&lt;p&gt;Bye Bye 👋&lt;/p&gt;
</content:encoded><category>ai</category><category>gemini</category><category>vibecoding</category><category>antigravity</category><category>Google Antigravity</category><category>vibe coding</category></item><item><title>Improve Your Git Commit Messages with GitLens Tips</title><link>https://delpuppo.net/blog/improve-your-git-commit-messages-with-gitlens-tips/</link><guid isPermaLink="true">https://delpuppo.net/blog/improve-your-git-commit-messages-with-gitlens-tips/</guid><description>In the AI era, we can do many different things with LLM: generate code, images, videos or ask...</description><pubDate>Fri, 03 Oct 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the AI era, we can do many different things with LLM: generate code, images, videos or ask whatever we want and wait for an answer.&lt;br /&gt;
The AI is here, and we cannot snub it. I love using it to simplify my day, help me find solutions, or learn new things. For instance, one of the most challenging tasks I perform every day is crafting a commit message for my next commit. I love to commit often, and I avoid commit messages like “WIP”, “work in progress”, “first step”, “second step”, and so on.&lt;br /&gt;
In the past, I spent a considerable amount of time crafting the perfect commit message for the next commit. Currently, thanks to &lt;a href=&quot;https://www.gitkraken.com/gitlens&quot;&gt;GitLens&lt;/a&gt; (by &lt;a href=&quot;https://www.gitkraken.com/&quot;&gt;GitKraken&lt;/a&gt;), I can ask for help from the AI to generate a prefilled message based on my actions, and then review the generated message.&lt;/p&gt;
&lt;h2&gt;How to generate messages&lt;/h2&gt;
&lt;p&gt;To generate the commit messages, first of all, you have to change your codebase 😎&lt;br /&gt;
After that, when you are ready to commit, it’s time to generate the message.&lt;br /&gt;
To do that, you need to go to the Source Control panel in &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VSCode,&lt;/a&gt; and if you have the &lt;a href=&quot;https://www.gitkraken.com/gitlens&quot;&gt;GitLens&lt;/a&gt; extension installed, you can use the “Magic” icon to generate the message.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;If you click the button, you should have three options&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Generate Commit Message with GitLens&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Compose Commit (Preview)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Switch GitLens AI Provider/Model&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;It goes without saying that the first option is the correct one to use when generating your commit message.&lt;/p&gt;
&lt;p&gt;After clicking the button, you must wait for a couple of seconds, and the result will appear in the text box.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the result is excellent. A commit message that follows the conventional commit rules and a small description of what happened in the code.&lt;/p&gt;
&lt;p&gt;Now, you can decide whether the message is okay and commit without changing it, or review it and then commit with your edited message.&lt;/p&gt;
&lt;h2&gt;Custom Instructions&lt;/h2&gt;
&lt;p&gt;As with all AI features, instructions are crucial to achieving the best possible result.&lt;br /&gt;
Also, for this feature, we can set up instructions to guide the AI in creating the messages.&lt;br /&gt;
To do that, you have to go to Settings and search for “GitLens commit message AI custom instruction”.&lt;br /&gt;
You should find an option “&lt;strong&gt;Gitlens › Ai › Generate Commit Message: Custom Instructions (Preview)”&lt;/strong&gt;, and this option has a text box that you can fill.&lt;br /&gt;
In my case, I inserted this instruction: “Please generate the commit message in the format of conventional commit,” but you can insert all the instructions that you want.&lt;br /&gt;
These instructions will help the AI generate the best messages based on your needs, and they will likely reduce the changes required to achieve the best message in the end.&lt;/p&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;As you can see, this feature is pretty simple but very helpful. It can reduce the time you spend generating commit messages and help you describe the intention of your commits in the best way.&lt;br /&gt;
I use it daily, and it helps me to be more precise in my commit messages, which in turn helps me summarise the commit in the best way.&lt;br /&gt;
&lt;em&gt;N.B. I’m not a native English speaker, and this feature helps me express myself in the best possible way in my commits.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Okay, that’s all, folks. I hope you’ve enjoyed the content and found it helpful.&lt;br /&gt;
See you soon&lt;/p&gt;
&lt;p&gt;Bye Bye 👋&lt;/p&gt;
</content:encoded><category>git</category><category>gitkraken</category><category>ai</category><category>gitlens</category><category>commit messages</category><category>commit</category></item><item><title>Do you really need the Cloud to work with AI?</title><link>https://delpuppo.net/blog/do-you-really-need-the-cloud-to-work-with-ai/</link><guid isPermaLink="true">https://delpuppo.net/blog/do-you-really-need-the-cloud-to-work-with-ai/</guid><description>We are in the AI era. New models emerge daily, and many applications have already integrated AI into...</description><pubDate>Wed, 25 Jun 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;We are in the AI era. New models emerge daily, and many applications have already integrated AI into their workflows.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gemini.google.com/&quot;&gt;Gemini&lt;/a&gt;, &lt;a href=&quot;https://openai.com/&quot;&gt;OpenAI&lt;/a&gt;, &lt;a href=&quot;https://copilot.microsoft.com/&quot;&gt;Copilot&lt;/a&gt;, &lt;a href=&quot;https://www.deepseek.com/&quot;&gt;Deepseek&lt;/a&gt;, &lt;a href=&quot;https://www.llama.com/&quot;&gt;Llama&lt;/a&gt;, and many others enable AI in your applications or help you write code, but they all need an internet connection to be accessible. You need the Cloud or to connect to a managed service to get an answer from the model. In some scenarios, this approach exposes you to security issues or the risk of sharing data with another service, and you may want to avoid it.&lt;/p&gt;
&lt;p&gt;To help the team and companies benefit from AI and avoid these issues, the Chrome team is working to make Gemini (nano) part of the Chrome browser. The idea is to download the models in the browser when you have connectivity and use them directly from the browser, offline, if needed.&lt;/p&gt;
&lt;p&gt;So let&apos;s see how it works 🚀&lt;/p&gt;
&lt;p&gt;&lt;em&gt;These features are on the building; most are available only under the Canary version and feature flag. If you are interested, you can find all the info at this&lt;/em&gt; &lt;a href=&quot;https://developer.chrome.com/docs/ai/built-in&quot;&gt;in this reference&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Features available&lt;/h2&gt;
&lt;p&gt;As you&apos;ve already understood, only limited features are available; some are stable, and some are not.&lt;/p&gt;
&lt;p&gt;Let&apos;s start by listing the features, and later, we will look at some of them.&lt;/p&gt;
&lt;p&gt;The available API are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/docs/ai/translator-api&quot;&gt;Translator API&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/docs/ai/language-detection&quot;&gt;Language Detector&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/docs/ai/summarizer-api&quot;&gt;Summarizer API&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/docs/ai/writer-api&quot;&gt;Writer API&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/docs/ai/rewriter-api&quot;&gt;Rewriter API&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/docs/ai/prompt-api&quot;&gt;Prompt API&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/docs/ai/built-in-apis#proofreader_api&quot;&gt;Proofreader API&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some are stable from Chrome 138, and some are available for local experiments; you can check out the status of the APIs &lt;a href=&quot;https://developer.chrome.com/docs/ai/built-in-apis#proofreader_api&quot;&gt;in this reference&lt;/a&gt; so you can be sure about the current situation when you read this post.&lt;/p&gt;
&lt;p&gt;As you can see, the APIs&apos; names are fantastic, and they explain their behaviour.&lt;/p&gt;
&lt;p&gt;If you want to try these features, start from &lt;a href=&quot;https://developer.chrome.com/docs/ai/get-started&quot;&gt;this documentation&lt;/a&gt; section. Unfortunately, you must enable the features through the configurations, so follow these steps to get a Chrome instance ready to run AI models directly from your laptop.&lt;/p&gt;
&lt;p&gt;Before closing this chapter, here is a quick reflection on these APIs. As you can notice, all of them work with text; some produce, some detect, some translate, and so on. So, for now, you can work with text and not produce images or videos from the browser, but it&apos;s a great starting point!&lt;/p&gt;
&lt;h2&gt;Let&apos;s talk about features&lt;/h2&gt;
&lt;h3&gt;Language Detector&lt;/h3&gt;
&lt;p&gt;The language detector API is one of the features available from Chrome 138. It allows you to detect the language of a specific word or phrase.&lt;/p&gt;
&lt;p&gt;It returns a list of possible languages with the confidence score for that language. This means that we need to make a strategy to choose the best language for our application, but in most cases, the language with the best score is the best one for our application!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How it works!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;One thing to do is check if the API is available or not to prevent errors.&lt;/p&gt;
&lt;p&gt;To do that, you must check the &lt;code&gt;self&lt;/code&gt; object.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (&apos;LanguageDetector&apos; in self) {
  // Language Detector Available
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, you must check if the model is already available in your browser or if you need to download it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const availability = await LanguageDetector.availability();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This result can have four possible values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&quot;unavailable&quot;&lt;/code&gt;: The requested options are unsupported, or the model cannot be prompted.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&quot;downloadable&quot;&lt;/code&gt;: The request is supported, but you need to download additional files before creating a session. These downloads may include the language model or fine-tuning.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&quot;downloading&quot;&lt;/code&gt;: The request is supported and a download is ongoing, which must be completed before creating a session..&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&quot;available&quot;&lt;/code&gt;: The request is supported, and you can create a session.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;This method is pretty much the same for all APIs. Following this flow, you can check if a specific API is available.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When you reach the &lt;code&gt;available&lt;/code&gt; status, you are finally ready to work with the &lt;strong&gt;LanguageDetector&lt;/strong&gt; API, and you can create an instance of it by following the next code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const instance = await LanguageDetector.create();
const result = await instance.detect(&apos;Hello world!&apos;);

// result = [{
//   detectedLanguage: &apos;en&apos;,
//   confidence: 0.9973934888839722
// }];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, this API is straightforward and pretty easy to learn.&lt;br /&gt;
With that, you have completed your first learning about AI in Chrome with Gemini Nano, and it’s time to move on to another fantastic API!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;N.B. If you are working with&lt;/em&gt; &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;&lt;em&gt;TypeScript&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and want to get the best DX possible, a types package that simplifies your work and enables IntelliSense for these APIs exists.&lt;/em&gt; &lt;code&gt;@types/dom-chromium-ai&lt;/code&gt; &lt;em&gt;This is the name of the package, and we have to thank you,&lt;/em&gt; &lt;a href=&quot;https://github.com/christianliebel&quot;&gt;&lt;em&gt;Christian Liebel&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://github.com/tomayac&quot;&gt;&lt;em&gt;Thomas Steiner&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, for it.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Translator API&lt;/h3&gt;
&lt;p&gt;Translator API is one of the most common features for an AI. It&apos;s pretty simple: you send a text, and you will receive the text translated. This API is available from Chrome 138.&lt;br /&gt;
But let’s see how it works.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How it works!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First, you must check if the API is available in the browser.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (&apos;Translator&apos; in self) {
  // Translator API available
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the API is enabled, you must check if the languages you need for source and target are available.&lt;br /&gt;
To do that, you must use the &lt;code&gt;availability&lt;/code&gt; method exposed by the &lt;code&gt;Translator&lt;/code&gt; object.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const translatorCapabilities = await Translator.availability({
  sourceLanguage: &apos;en&apos;,
  targetLanguage: &apos;it&apos;,
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result of this method can have four different values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&quot;unavailable&quot;&lt;/code&gt;: The implementation does not support translation of the given languages.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&quot;downloadable&quot;&lt;/code&gt;: The implementation supports translation of the given languages, but a download is required to proceed. The download may be the browser model.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&quot;downloading&quot;&lt;/code&gt;: The implementation supports translation of the given languages. The browser is finishing an ongoing download, as part of creating the associated object.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&quot;available&quot;&lt;/code&gt;: The implementation supports translation of the given languages, and any required downloads are already complete.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, if you don’t receive &lt;code&gt;&quot;unavailable&quot;&lt;/code&gt;, you can create the translator instance. This method will download the model for you if it hasn’t already been downloaded.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const translator = await Translator.create({
  sourceLanguage: &apos;en&apos;,
  targetLanguage: &apos;it&apos;,
  monitor(m) {
    m.addEventListener(&apos;downloadprogress&apos;, (e) =&amp;gt; {
      console.log(`Downloaded ${e.loaded * 100}%`);
    });
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, using the &lt;code&gt;create&lt;/code&gt; method, you can create your instance and pass your source and target languages. Then, using the &lt;code&gt;monitor&lt;/code&gt; method, you can listen to the download progress and maybe create a loader for the user to provide feedback and create a better UX experience. Obviously, the promise will fail if something goes wrong during the download, and you must handle it.&lt;br /&gt;
But if everything is okay, you can use the new &lt;code&gt;translator&lt;/code&gt; instance to translate the text by using the &lt;code&gt;translate&lt;/code&gt; method.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;await translator.translate(&apos;Where is the next bus stop, please?&apos;);
// Dov&apos;è la prossima fermata dell&apos;autobus, per favore?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One important thing to know about this API is that it processes messages sequentially. So, if you have many messages, you must keep this limitation in mind. Then, if you need to translate large amounts of text, it’s better to chunk it and create a &lt;a href=&quot;https://web.dev/articles/building/a-loading-bar-component&quot;&gt;loading interface&lt;/a&gt; as feedback for the user.&lt;/p&gt;
&lt;p&gt;As is evident, this API is also straightforward. There are some methods to learn, and you can integrate this API into your applications by using them.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Also, for this API, you can use the&lt;/em&gt; &lt;code&gt;@types/dom-chromium-ai&lt;/code&gt; &lt;em&gt;package to get a better experience with&lt;/em&gt; &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;&lt;em&gt;TypeScript&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;Summarizer API&lt;/h3&gt;
&lt;p&gt;The last API you will meet in this article is the Summarizer API.&lt;br /&gt;
This API enable you to summarise small or large text. Also, this API is available from Chrome 138 stable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How it works!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;First, you must check if the API is available in the browser.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (&apos;Summarizer&apos; in self) {
  // Summarizer API available
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If the API is enabled, then you must check if the model is available.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const summarizerCapabilities = await Summarizer.availability();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also, for this method, the possible results can be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&quot;unavailable&quot;&lt;/code&gt; means that the implementation does not support the requested options.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&quot;downloadable&quot;&lt;/code&gt; means that the implementation supports the requested options, but first, the browser has to download something, such as a model (in Chrome&apos;s case, Gemini Nano) or fine-tuning for the model.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&quot;downloading&quot;&lt;/code&gt; means that the implementation supports the requested options, but it has to finish an ongoing download before it can proceed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;&quot;available&quot;&lt;/code&gt; means that the implementation supports the requested options and the summarizer can proceed.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, if everything is okay, it’s time to create an instance of the Summarizer API.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const summarizer = await Summarizer.create({
  monitor(m) {
    m.addEventListener(&apos;downloadprogress&apos;, (e) =&amp;gt; {
      console.log(`Downloaded ${e.loaded * 100}%`);
    });
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This &lt;code&gt;create&lt;/code&gt; method exposes the &lt;code&gt;monitor&lt;/code&gt; function to listen to the download progress and create a better experience for the user as well.&lt;br /&gt;
This &lt;code&gt;create&lt;/code&gt; method has different parameters you can pass to get different types of summaries or drive the summary&apos;s length.&lt;/p&gt;
&lt;p&gt;These parameters are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;sharedContext&lt;/code&gt;: Additional shared context that can help the summarizer.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;type&lt;/code&gt;: The type of summarisation, with the allowed values &lt;code&gt;key-points&lt;/code&gt; (&lt;em&gt;&lt;strong&gt;default&lt;/strong&gt;&lt;/em&gt;), &lt;code&gt;tldr&lt;/code&gt;, &lt;code&gt;teaser&lt;/code&gt;, and &lt;code&gt;headline&lt;/code&gt;. To learn more about them, follow this &lt;a href=&quot;https://developer.chrome.com/docs/ai/summarizer-api&quot;&gt;in this reference&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;format&lt;/code&gt;: The format of the summarisation, with the allowed values &lt;code&gt;markdown&lt;/code&gt; (default) and &lt;code&gt;plain-text&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;length&lt;/code&gt;: The length of the summarisation, with the allowed values &lt;code&gt;short&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt; (default), and &lt;code&gt;long&lt;/code&gt;. The meanings of these lengths vary depending on the requested &lt;code&gt;type&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&apos;s important to know that parameters can’t be changed. So, once you create a new instance, if you need to modify the parameters, you must create a new instance.&lt;/p&gt;
&lt;p&gt;Now that you have the summarizer instance, you can use it to summarise the text.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const longText = &apos;Blah blah blah......&apos;;
const summary = await summarizer.summarize(longText, {
  context: &apos;This is a recipe.&apos;,
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This API also exposes another method, just in case you want to stream the summary result and make it available “faster.”&lt;br /&gt;
To do that, you need to use the &lt;code&gt;summarizeStreaming&lt;/code&gt; method instead of the &lt;code&gt;summarize&lt;/code&gt; one.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const longText = &apos;Blah blah blah......&apos;;
const summary = await summarizer.summarizeStreaming(longText, {
  context: &apos;This is a recipe.&apos;,
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And with that, you learnt the last AI API for Browsers available in this article 😃&lt;/p&gt;
&lt;p&gt;Like the others, this API is straightforward too. There are just some methods to know, and you can integrate this API into your applications.&lt;/p&gt;
&lt;h2&gt;Recipe Radar with AI App&lt;/h2&gt;
&lt;p&gt;I wrote a lot in this article, I know, but to let you know how these APIs work. I created a sample app with some recipes. On the detail page, you can see the Language Detector and Translator API in action. Therefore, on the search page, you can see the Summarizer API in action to summarise the recipe and return a summary of the recipe to the user.&lt;br /&gt;
If you are interested in it, here is the link to the repo and to the website:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;Github Repo&lt;/em&gt;: &lt;a href=&quot;https://github.com/Puppo/recipe-radar-with-ai&quot;&gt;https://github.com/Puppo/recipe-radar-with-ai&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;GitHub Page Website:&lt;/em&gt; &lt;a href=&quot;https://puppo.github.io/recipe-radar-with-ai/&quot;&gt;https://puppo.github.io/recipe-radar-with-ai/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please don’t take too much care of the code structure. I vibe-coded the application&apos;s structure to reduce the time it took to create, and I spent more time on the AI feature and its integration.&lt;/p&gt;
&lt;p&gt;By the way, this application example implements and runs all these APIS on a website. It’s important to test in a Chrome version with these APIs available.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Okay, it’s time to wrap up!&lt;br /&gt;
In this article, you learn how to integrate AI inside the Browser without relying on any services or cloud providers.&lt;br /&gt;
You learnt how to use Language Detector, Translator, and Summarizer API on the Web and what they look like.&lt;br /&gt;
Remember that these new features are not available in all browsers, so please be careful when using them in production.&lt;/p&gt;
&lt;p&gt;That’s it, folks. I hope you enjoyed the content. If so, please leave a comment or a reaction!&lt;/p&gt;
&lt;p&gt;See you soon with other awesome content 🚀&lt;/p&gt;
&lt;p&gt;Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Google Cloud credits are provided for this project.&lt;/em&gt; #AISprint&lt;/p&gt;
</content:encoded><category>aisprint</category><category>gemini</category><category>ai</category><category>chrome</category><category>gemini-nano</category><category>geminiAPI</category></item><item><title>A Promise is forever</title><link>https://delpuppo.net/blog/a-promise-is-forever/</link><guid isPermaLink="true">https://delpuppo.net/blog/a-promise-is-forever/</guid><description>In the ever-evolving world of web development, mastering asynchronous operations is a crucial skill...</description><pubDate>Tue, 06 Feb 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the ever-evolving world of web development, mastering asynchronous operations is a crucial skill for any JavaScript developer. Asynchronous programming allows web applications to handle tasks like API requests, file operations, or any activities that require waiting for results without blocking the main thread. Traditionally, this was managed through callback functions, leading to the infamous &quot;callback hell,&quot; where code becomes tangled and difficult to maintain. Enter JavaScript Promises - a powerful and elegant solution to simplify asynchronous code management.&lt;/p&gt;
&lt;p&gt;Promises in JavaScript represent the eventual completion or failure of an asynchronous operation and its resulting value. They not only provide a cleaner and more manageable way to handle asynchronous tasks but also offer improved error handling and readability. This makes them an indispensable tool in the modern JavaScript developer&apos;s toolkit.&lt;/p&gt;
&lt;p&gt;In this comprehensive guide, we&apos;ll embark on a journey to unravel the mysteries of JavaScript Promises. From their fundamental concepts to advanced techniques, we will explore how Promises can streamline your code and make handling asynchronous operations a breeze. Whether you&apos;re just starting your journey with JavaScript or are a seasoned developer, this post aims to enhance your understanding and skills in working with Promises.&lt;/p&gt;
&lt;p&gt;So, let&apos;s dive in and unlock the full potential of JavaScript Promises, transforming the way you write and manage asynchronous code!&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Section 1: Understanding Promises&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;What is a Promise?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;At its core, a JavaScript Promise is an object that represents the eventual completion or failure of an asynchronous operation and its resulting value. Unlike the immediate return of values in synchronous code, a Promise gives us a placeholder for a future value, which we can work with in a more structured and predictable manner.&lt;/p&gt;
&lt;p&gt;This approach solves many issues associated with older, callback-based patterns, commonly known as &quot;callback hell.&quot; Promises allow for more readable and maintainable code, especially when dealing with complex sequences of asynchronous operations.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Creating a Promise&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A Promise in JavaScript is created using the &lt;code&gt;Promise&lt;/code&gt; constructor. It takes a function as its argument, known as the executor function. This executor function is called immediately by the Promise implementation and it receives two functions as parameters: &lt;code&gt;resolve&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;resolve&lt;/code&gt; is called when the asynchronous task completes successfully, passing the result.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;reject&lt;/code&gt; is used when the task fails, passing the error or reason for failure.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&apos;s a basic example of creating a Promise:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let myPromise = new Promise((resolve, reject) =&amp;gt; {
  // Asynchronous operation code here
  if(/* operation successful */) {
    resolve(&apos;Success&apos;);
  } else {
    reject(&apos;Error&apos;);
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, the Promise will either resolve with &lt;code&gt;Success&lt;/code&gt; or reject with &lt;code&gt;Error&lt;/code&gt;, depending on the outcome of the asynchronous operation encapsulated within it.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Promise States&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A Promise can be in one of three states:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Pending&lt;/strong&gt; : The initial state of a Promise. The operation has not been completed yet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fulfilled&lt;/strong&gt; : The operation was completed successfully, and the Promise now holds the resulting value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Rejected&lt;/strong&gt; : The operation failed, and the Promise holds the reason for the failure.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This state model ensures that a Promise can only be resolved or rejected once and its state and value become immutable after that change.&lt;/p&gt;
&lt;p&gt;Understanding these foundational concepts is crucial for working effectively with Promises in JavaScript. They form the building blocks upon which more complex asynchronous operations can be built, allowing for more readable and maintainable code.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Section 2: Working with Promises&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;then, catch, and finally&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;After creating a Promise, the next step is handling its resolution or rejection. This is where the methods &lt;code&gt;then&lt;/code&gt;, &lt;code&gt;catch&lt;/code&gt;, and &lt;code&gt;finally&lt;/code&gt; come into play.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;then&lt;/strong&gt; : This method is used to access the result of a Promise if it is successfully resolved. It takes up to two functions as arguments: the first for the resolved case and the second for the rejected case.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;catch&lt;/strong&gt; : This method is used for error handling in Promises. It is essentially a shorthand for &lt;code&gt;then(null, rejection)&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;finally&lt;/strong&gt; : Introduced in ES2018, &lt;code&gt;finally&lt;/code&gt; is a method that executes a specified piece of code when the Promise is settled, regardless of its outcome (resolved or rejected). It&apos;s useful for cleanup actions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;Chaining Promises&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;One of the key strengths of Promises is their ability to be chained. This is done by returning another Promise in the &lt;code&gt;then&lt;/code&gt; method, which allows for sequential asynchronous operations.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;new Promise((resolve, reject) =&amp;gt; {
  setTimeout(() =&amp;gt; resolve(1), 1000);})
  .then(result =&amp;gt; {
    console.log(result); // 1
    return result * 2;
  })
  .then(result =&amp;gt; {
    console.log(result); // 2
    return result * 3;
  })
  .then(result =&amp;gt; {
    console.log(result); // 6
    return result * 4;
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this chain, each &lt;code&gt;then&lt;/code&gt; receives the result of the previous operation, allowing for a sequence of asynchronous tasks to be handled in a clean and readable manner.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Error Handling in Promises&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Error handling is crucial in asynchronous code. In a Promise chain, if an error is thrown in any of the &lt;code&gt;then&lt;/code&gt; methods, it propagates down the chain until it is caught by a &lt;code&gt;catch&lt;/code&gt; method. This makes it easier to manage errors in complex asynchronous code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;doSomething()
  .then(result =&amp;gt; doSomethingElse(result))
  .then(newResult =&amp;gt; doThirdThing(newResult))
  .catch(error =&amp;gt; console.error(error))
  .finally(() =&amp;gt; console.log(&apos;Operation done&apos;));
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;strong&gt;Real-world Examples&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Promises are particularly useful when dealing with API requests. For example, fetching data from a remote server:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fetch(&apos;https://api.example.com/data&apos;)
  .then(response =&amp;gt; response.json())
  .then(data =&amp;gt; console.log(data))
  .catch(error =&amp;gt; console.error(&apos;Error:&apos;, error));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This section on working with Promises is critical for understanding how to effectively implement and manage asynchronous operations in JavaScript. It covers the fundamental methods for handling Promises and demonstrates the power of chaining for complex tasks, along with practical examples that the readers can relate to and implement in their own projects.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Section 3: Advanced Promise Concepts&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Async/Await Syntax&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Introduced in ES2017, async/await is a syntactic feature in JavaScript that allows you to work with Promises in a more synchronous-like manner, making your asynchronous code look and behave a bit more like synchronous code.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Async Functions&lt;/strong&gt; : Declaring a function as &lt;code&gt;async&lt;/code&gt; automatically wraps its return value in a Promise. This means you can use &lt;code&gt;await&lt;/code&gt; within these functions to pause the execution until the awaited Promise is resolved.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Await&lt;/strong&gt; : The &lt;code&gt;await&lt;/code&gt; keyword is used to pause the execution of an async function until a Promise is resolved, allowing you to write cleaner and more readable asynchronous code.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;Error Handling in Async/Await&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Error handling in async/await is achieved using try/catch blocks, making it syntactically similar to synchronous error handling.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;async function safeFetch() {
  try {
    const response = await fetch(&apos;https://api.example.com/data&apos;);
    return await response.json();
  } catch (error) {
    console.error(&apos;Fetch failed:&apos;, error);
    throw error; // Re-throwing the error is important for caller awareness
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;strong&gt;Handling Multiple Promises&lt;/strong&gt;&lt;/h3&gt;
&lt;h4&gt;Promise.all&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;Promise.all&lt;/code&gt; is used when you need to wait for multiple Promises to complete. It takes an array of Promises and returns a new Promise that resolves when all of the input Promises resolve or rejects as soon as one of them rejects.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Promise.all([asyncTask1(), asyncTask2(), asyncTask3()])
  .then(results =&amp;gt; {
    console.log(&apos;All tasks completed:&apos;, results);
  })
  .catch(error =&amp;gt; {
    console.error(&apos;One of the tasks failed:&apos;, error);
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Promise.race&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;Promise.race&lt;/code&gt; resolves or rejects as soon as one of the Promises in an iterable resolves or rejects, with the value or reason from that Promise.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Promise.race([asyncTask1(), asyncTask2(), asyncTask3()])
  .then(result =&amp;gt; {
     console.log(&apos;First task completed:&apos;, result);
  })
  .catch(error =&amp;gt; {
      console.error(&apos;One of the tasks failed:&apos;, error);
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Promise.allSettled&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;Promise.allSettled&lt;/code&gt; is a method that returns a Promise that resolves after all of the given Promises have either been resolved or rejected, with an array of objects describing the outcome of each Promise.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Promise.allSettled([asyncTask1(), asyncTask2(), asyncTask3()])
  .then(results =&amp;gt; {
     results.forEach((result) =&amp;gt; {
       if (result.status === &apos;fulfilled&apos;) {
         console.log(&apos;Success:&apos;, result.value);
       } else {
         console.log(&apos;Failure:&apos;, result.reason);
       }
     });
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Promise.any&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;Promise.any&lt;/code&gt; takes multiple Promises and as soon as one of the Promises resolves, it returns a single Promise that resolves with the value from that Promise. If all of the passed-in Promises reject, then the returned Promise is rejected with an &lt;code&gt;AggregateError&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Promise.any([asyncTask1(), asyncTask2(), asyncTask3()])
  .then(result =&amp;gt; {
    console.log(&apos;First successful task:&apos;, result);
  })
  .catch(error =&amp;gt; {
    console.error(&apos;All promises failed:&apos;, error);
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These methods for handling multiple Promises are powerful tools in a JavaScript developer&apos;s arsenal. They offer different ways to manage multiple asynchronous operations, making it easier to write clean and efficient code. Understanding when and how to use each of these methods can significantly improve the way you handle concurrency in JavaScript.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Understanding Promise.withResolvers&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;In the realm of JavaScript Promises, &lt;code&gt;Promise.withResolvers&lt;/code&gt; could be conceptualized as a utility function designed to enhance the flexibility and control over Promise resolution and rejection. Unlike the standard Promise constructor, which encapsulates the executor function, &lt;code&gt;Promise.withResolvers&lt;/code&gt; could provide direct access to the &lt;code&gt;resolve&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt; functions outside the Promise context. This feature would be particularly useful in scenarios where the resolution or rejection of a Promise needs to be triggered externally or in more complex control flows.&lt;/p&gt;
&lt;p&gt;Imagine &lt;code&gt;Promise.withResolvers&lt;/code&gt; functioning as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Promise.withResolvers = Promise.withResolvers ?? function() { 
  let resolve, reject;
  const promise = new Promise((res, rej) =&amp;gt; {
    resolve = res;
    reject = rej;
  });
  return { promise, resolve, reject };
}

const { promise, resolve, reject } = Promise.withResolvers();

promise
  .then(value =&amp;gt; console.log(`Resolved with: ${value}`))
  .catch(error =&amp;gt; 
    console.error(`Rejected with: ${error}`));
// The Promise can be resolved or rejected externally
resolve(&quot;Success!&quot;);
// or reject(&quot;Failure&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this hypothetical implementation, &lt;code&gt;Promise.withResolvers&lt;/code&gt; returns an object containing the Promise itself and its respective &lt;code&gt;resolve&lt;/code&gt; and &lt;code&gt;reject&lt;/code&gt; functions. This setup offers a more declarative way of handling Promises, especially in cases where the resolution condition is not immediately known or is dependent on external factors.&lt;/p&gt;
&lt;p&gt;This approach, while offering more control, also requires careful management to avoid issues like unresolved Promises or memory leaks. It exemplifies the flexibility of Promises in JavaScript and how they can be tailored to fit specific programming paradigms or application needs. This method has been implemented in ES2023 but creates a polyfill for it; it is really a piece of cake as you can see.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Section 4: Under the Hood&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Event Loop and Promises&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;JavaScript&apos;s concurrency model revolves around the Event Loop, which plays a critical role in executing asynchronous code like Promises. Understanding this mechanism is key to mastering JavaScript&apos;s asynchronous behavior.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Event Loop&lt;/strong&gt; : JavaScript has a single-threaded runtime, meaning it can only execute one command at a time. The event loop enables non-blocking operations by offloading tasks like I/O, timers, and HTTP requests, which are handled outside the JavaScript engine.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Role of Promises&lt;/strong&gt; : When a Promise is resolved or rejected, its callback is moved to the Microtask Queue, which is processed after the current execution stack is complete but before the event loop continues to the next iteration. This ensures that Promise callbacks are executed as soon as the JavaScript engine has the opportunity to do so, maintaining the non-blocking nature of asynchronous operations.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;Creating Custom Promises&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;While many asynchronous operations are handled by built-in functions returning Promises, there are scenarios where you might need to create your own Promises.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Custom Promise Example&lt;/strong&gt; : Let&apos;s say you&apos;re interfacing with a legacy API that uses callbacks, and you want to adapt it to use Promises for better code consistency and readability.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;function legacyApiFunction(callback) {
  // Simulating a callback-based API
  setTimeout(() =&amp;gt; {
    const data = &apos;some data&apos;;
    callback(null, data);
  }, 1000);
}

function promisifyLegacyApi() {
  return new Promise((resolve, reject) =&amp;gt; {
    legacyApiFunction((err, data) =&amp;gt; {
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    });
  });
}

promisifyLegacyApi()
  .then(data =&amp;gt; console.log(data))
  .catch(error =&amp;gt; console.error(error));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, &lt;code&gt;promisifyLegacyApi&lt;/code&gt; wraps the old callback-style function in a new Promise, providing a more modern, Promise-based interface for the same functionality.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Best Practices and Pitfalls&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Avoiding the &quot;Promise Hell&quot;&lt;/strong&gt; : Similar to &quot;callback hell,&quot; it&apos;s possible to end up in a situation with deeply nested Promises. To avoid this, leverage chaining and return Promises from within &lt;code&gt;then&lt;/code&gt; callbacks, keeping the code flat.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Error Handling&lt;/strong&gt; : Always handle errors in Promises, either using &lt;code&gt;catch&lt;/code&gt; for individual Promises or global error handlers for unhandled Promise rejections.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Debugging&lt;/strong&gt; : Debugging asynchronous code can be tricky. Utilize modern tools and techniques such as browser developer tools, which provide features to track and inspect Promises.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to dive deep into Promise, don&apos;t leave my YouTube video about it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=ROwJX3i_m2Q&quot;&gt;https://www.youtube.com/watch?v=ROwJX3i_m2Q&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;As we conclude our journey through the world of JavaScript Promises, it&apos;s clear that they are much more than just a tool for handling asynchronous operations. They represent a fundamental shift in how we write and think about asynchronous code in JavaScript, offering a robust and elegant way to manage complex operations.&lt;/p&gt;
&lt;p&gt;From understanding the basics of what a Promise is and how to create one, to exploring advanced concepts like &lt;code&gt;Promise.all&lt;/code&gt;, &lt;code&gt;Promise.race&lt;/code&gt;, &lt;code&gt;Promise.allSettled&lt;/code&gt;, and &lt;code&gt;Promise.any&lt;/code&gt;, we&apos;ve covered a broad spectrum of functionalities that Promises provide. The async/await syntax further simplifies working with Promises, allowing for code that is not only more readable but also easier to maintain.&lt;/p&gt;
&lt;p&gt;The real power of Promises lies in their ability to streamline complex asynchronous tasks, making our code cleaner, more efficient, and more reliable. By understanding the event loop and how Promises fit into JavaScript&apos;s concurrency model, developers can write more performant and bug-free code.&lt;/p&gt;
&lt;p&gt;As you incorporate these concepts into your daily coding practices, remember that mastering Promises is a journey. There&apos;s always more to learn and new patterns to explore. Keep experimenting, keep learning, and most importantly, keep coding. The world of JavaScript is constantly evolving, and with tools like Promises at your disposal, you&apos;re well-equipped to tackle the challenges of modern web development.&lt;/p&gt;
&lt;p&gt;Happy coding!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this article&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/JavaScript-Examples/tree/01-promises&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>es6</category><category>promise</category><category>abotwrotethis</category><category>promises</category><category>async</category></item><item><title>The Reflect API: The Swiss Army Knife Every JavaScript Developer Needs</title><link>https://delpuppo.net/blog/javascript-you-dont-know/the-reflect-api-the-swiss-army-knife-every-javascript-developer-needs/</link><guid isPermaLink="true">https://delpuppo.net/blog/javascript-you-dont-know/the-reflect-api-the-swiss-army-knife-every-javascript-developer-needs/</guid><description>Ever wished for a magical toolkit that gives you superhero-like control over JavaScript objects? Say...</description><pubDate>Thu, 09 Nov 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ever wished for a magical toolkit that gives you superhero-like control over JavaScript objects? Say hello to the &lt;code&gt;Reflect&lt;/code&gt; API, the Swiss Army knife every modern JavaScript developer needs! From peeping into objects to conjuring custom behaviors &lt;code&gt;Reflect&lt;/code&gt;is your one-stop spellbook! 📜&lt;/p&gt;
&lt;p&gt;Strap in as we teleport through this arcane realm of JavaScript, where we&apos;ll not only decode &lt;code&gt;Reflect&lt;/code&gt;, but also empower you with hands-on examples and practical tips! 🚀&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;🎯 Core Objectives of Reflect&lt;/strong&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Introspection&lt;/strong&gt; : Much like looking into a magic mirror, &lt;code&gt;Reflect&lt;/code&gt; allows you to delve into an object&apos;s properties and characteristics, enabling you to perform introspective tasks like checking property existence or retrieving property descriptors.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Manipulation&lt;/strong&gt; : Think of &lt;code&gt;Reflect&lt;/code&gt; as your Swiss Army knife for object operations. You can easily add, delete, or modify object properties and even trap or monitor these operations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Extensibility&lt;/strong&gt; : The &lt;code&gt;Reflect&lt;/code&gt; API can be seen as a foundational layer that sets the stage for creating Proxy objects, empowering you to build custom behaviors for basic operations (like property lookup, assignment, enumeration, and more).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;🛠 &lt;strong&gt;Reflect Methods&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;1. &lt;code&gt;Reflect.apply()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Forget the complexities of &lt;code&gt;Function.prototype.apply()&lt;/code&gt;! With &lt;code&gt;Reflect.apply()&lt;/code&gt;, invoking functions is a breeze.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const numbers = [1, 2, 3];
const sum = (a, b, c) =&amp;gt; a + b + c;

// Using Reflect.apply()
const result = Reflect.apply(sum, null, numbers);

console.log(result); // Output: 6
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. &lt;code&gt;Reflect.get()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Tired of the limitations of vanilla property retrieval? &lt;code&gt;Reflect.get()&lt;/code&gt; offers more control and flexibility.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const obj = { x: 42, y: &apos;hello&apos; };

// Using Reflect.get()
const value = Reflect.get(obj, &apos;x&apos;);

console.log(value); // Output: 42
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. &lt;code&gt;Reflect.set()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Modify properties with pinpoint accuracy, even within complex object hierarchies.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const obj = { x: 42 };

// Using Reflect.set()
Reflect.set(obj, &apos;x&apos;, 13);

console.log(obj.x); // Output: 13
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. &lt;code&gt;Reflect.defineProperty()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Defining properties with their descriptors has never been easier!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const obj = {};

// Using Reflect.defineProperty()
Reflect.defineProperty(obj, &apos;x&apos;, { value: 42, writable: false });

console.log(obj.x); // Output: 42
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;5. &lt;code&gt;Reflect.deleteProperty()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Wipe properties off the face of your object as if they never existed.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const obj = { x: 42 };

// Using Reflect.deleteProperty()
Reflect.deleteProperty(obj, &apos;x&apos;);

console.log(&apos;x&apos; in obj); // Output: false
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6. &lt;code&gt;Reflect.ownKeys()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Discover all the keys an object owns, including Symbols!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const obj = { x: 42, [Symbol(&apos;key&apos;)]: &apos;symbolValue&apos; };

// Using Reflect.ownKeys()
const keys = Reflect.ownKeys(obj);

console.log(keys); // Output: [&apos;x&apos;, Symbol(key)]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;🚀 &lt;strong&gt;Why Use Reflect?&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;By now, you might be asking yourself, &quot;Why should I dive into &lt;code&gt;Reflect&lt;/code&gt; when there are other ways to manipulate and inspect JavaScript objects?&quot; Great question! Let&apos;s unravel the reasons that make &lt;code&gt;Reflect&lt;/code&gt; a powerful tool in your JavaScript arsenal.&lt;/p&gt;
&lt;h3&gt;1. Functional Paradigm&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;Reflect&lt;/code&gt; API offers static methods that embrace the functional programming paradigm, making them first-class citizens that you can pass around in your code.&lt;/p&gt;
&lt;p&gt;👉 &lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Suppose you want to make property retrieval generic. You can do so with ease.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const genericGet = Reflect.get;
const value = genericGet(someObject, &apos;someProperty&apos;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. Enhanced Error Handling&lt;/h3&gt;
&lt;p&gt;Unlike methods in the &lt;code&gt;Object&lt;/code&gt; API that often throw errors, &lt;code&gt;Reflect&lt;/code&gt; methods return a Boolean to indicate success or failure, allowing for more elegant error handling.&lt;/p&gt;
&lt;p&gt;👉 &lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;Reflect.set()&lt;/code&gt;, you can check if a property was set successfully and proceed accordingly.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (Reflect.set(obj, &apos;key&apos;, &apos;value&apos;)) {
    // Property was set successfully
} else {
    // Failed to set the property
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. Proxy Integration&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Reflect&lt;/code&gt; and &lt;code&gt;Proxy&lt;/code&gt; are like two peas in a pod. The methods available in &lt;code&gt;Reflect&lt;/code&gt; align perfectly with &lt;code&gt;Proxy&lt;/code&gt; traps, allowing for seamless and straightforward custom behaviors.&lt;/p&gt;
&lt;p&gt;👉 &lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Creating a logging proxy becomes ridiculously simple.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const handler = {
    get(target, property) {
        console.log(`Reading property: ${property}`);
        return Reflect.get(target, property);
    }
};
const proxy = new Proxy(someObject, handler);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. Consistency and Predictability&lt;/h3&gt;
&lt;p&gt;Methods in &lt;code&gt;Reflect&lt;/code&gt; offer a more consistent API. They always return values (often Booleans) instead of throwing errors, and the parameter orders are predictable, leading to cleaner and more maintainable code.&lt;/p&gt;
&lt;p&gt;👉 &lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Both &lt;code&gt;Reflect.get()&lt;/code&gt; and &lt;code&gt;Reflect.set()&lt;/code&gt; have consistent argument ordering: &lt;code&gt;target, propertyKey[, receiver]&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Reflect.get(target, property);
Reflect.set(target, property, value);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;5. Intuitive and Self-Documenting&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Reflect&lt;/code&gt; methods are often more intuitive and self-documenting than their &lt;code&gt;Object&lt;/code&gt; counterparts. This readability makes it easier for developers, new and experienced alike, to understand the code.&lt;/p&gt;
&lt;p&gt;👉 &lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Compare &lt;code&gt;Reflect.ownKeys(obj)&lt;/code&gt; with &lt;code&gt;Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj))&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Which one do you find more intuitive?&lt;/p&gt;
&lt;h3&gt;6. Future-Proofing&lt;/h3&gt;
&lt;p&gt;As JavaScript evolves, new methods are more likely to be added to the &lt;code&gt;Reflect&lt;/code&gt; API, making it a wise choice for long-term projects.&lt;/p&gt;
&lt;p&gt;For more info don&apos;t waste my YouTube video on my &lt;a href=&quot;https://www.youtube.com/@Puppo_92&quot;&gt;&lt;strong&gt;YouTube Channel&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=gaCvSu3ncbw&quot;&gt;https://www.youtube.com/watch?v=gaCvSu3ncbw&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;And just like that, we&apos;ve come to the end of our magical journey through the labyrinthine world of JavaScript&apos;s &lt;code&gt;Reflect&lt;/code&gt; API! You&apos;re now armed with the tools, tricks, and spells—err methods—to perform object manipulation wizardry that would make Dumbledore proud.&lt;/p&gt;
&lt;p&gt;Ready to cast your own spells? Grab your keyboard wand, and let&apos;s make the JavaScript realm a little more enchanted, one &lt;code&gt;Reflect&lt;/code&gt; method at a time!&lt;/p&gt;
&lt;p&gt;Remember, the magic isn&apos;t just in the code; it&apos;s in you, the coding sorcerer who brings it to life. Until our next spellbinding adventure, code on, wizards! 🚀&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this article&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/javascript-you-dont-know/tree/08-reflect-api&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>reflect</category><category>js</category></item><item><title>Cracking the JavaScript Code: Unveil the Magic of Object Property Descriptors</title><link>https://delpuppo.net/blog/javascript-you-dont-know/cracking-the-javascript-code-unveil-the-magic-of-object-property-descriptors/</link><guid isPermaLink="true">https://delpuppo.net/blog/javascript-you-dont-know/cracking-the-javascript-code-unveil-the-magic-of-object-property-descriptors/</guid><description>👋 Hey, JavaScript developers! Ever wondered what makes your objects tick? Or how to go all...</description><pubDate>Thu, 02 Nov 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;👋 Hey, JavaScript developers!&lt;/p&gt;
&lt;p&gt;Ever wondered what makes your objects tick? Or how to go all &quot;Inception&quot; on your JavaScript code by manipulating object properties at a deeper, more granular level? Well, you&apos;re in luck! Today, we&apos;re diving into the magical world of Object Property Descriptors in JavaScript—a realm where you become the puppet master of your objects. 🎭&lt;/p&gt;
&lt;p&gt;Get ready for a roller coaster ride that takes you through the hidden alleys of JavaScript&apos;s objects. By the end of this post, you&apos;ll be wielding Object Property Descriptors like a wizard casting spells, giving you full control over properties, and even the behaviour of your objects. 🧙&lt;/p&gt;
&lt;h2&gt;What is a JavaScript Object Property Descriptor?&lt;/h2&gt;
&lt;p&gt;In JavaScript, objects are more than just key-value pairs. They&apos;re intricate entities with characteristics that often go unnoticed, hidden beneath the surface like an iceberg in an ocean of code. Welcome to the fascinating realm of Object Property Descriptors, a tool that lets you truly tap into the full potential of JavaScript objects.&lt;/p&gt;
&lt;p&gt;An Object Property Descriptor is essentially a metadata object that details how a property on an object behaves. It&apos;s like the DNA of the property, encoding its attributes and defining its characteristics. You can think of an Object Property Descriptor as a control panel, giving you knobs and levers to fine-tune how a property can be accessed, modified, enumerated, or deleted.&lt;/p&gt;
&lt;p&gt;Here are the attributes you can configure with an Object Property Descriptor:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;value&lt;/code&gt;: The actual value of the property. Simple enough, right? 📦&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;writable&lt;/code&gt;: Determines if the property value can be changed. It&apos;s like a lock that you can engage or disengage at will. 🔒&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;enumerable&lt;/code&gt;: Controls whether the property shows up during enumeration, like when you use a &lt;code&gt;for...in&lt;/code&gt; loop or &lt;code&gt;Object.keys()&lt;/code&gt;. It&apos;s like a spotlight—or lack thereof—on your property. 🔦&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;configurable&lt;/code&gt;: Decides if the property can be deleted or has its attributes changed. Think of it as the ultimate veto power. 🛑&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can access and modify these attributes using built-in JavaScript methods like &lt;code&gt;Object.getOwnPropertyDescriptor()&lt;/code&gt;, &lt;code&gt;Object.defineProperty()&lt;/code&gt;, and &lt;code&gt;Object.defineProperties()&lt;/code&gt;. These are your magic wands to perform spellbinding feats of object manipulation!&lt;/p&gt;
&lt;p&gt;For example, to make a property read-only, you can set its &lt;code&gt;writable&lt;/code&gt; attribute to &lt;code&gt;false&lt;/code&gt;. Or if you want to hide a property from enumeration, just set the &lt;code&gt;enumerable&lt;/code&gt; attribute to &lt;code&gt;false&lt;/code&gt;. It&apos;s like tailoring your object properties to fit your exact needs, almost as if you&apos;re crafting a bespoke suit!&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;Object Property Descriptors in Practice&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;It&apos;s time to get our hands dirty and jump into the practical aspects of using Object Property Descriptors in JavaScript.&lt;/p&gt;
&lt;h3&gt;1. Accessing Descriptors with &lt;code&gt;Object.getOwnPropertyDescriptor()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Let&apos;s start with the basics. Ever wondered what the descriptor of an existing object property looks like? &lt;code&gt;Object.getOwnPropertyDescriptor()&lt;/code&gt; is your answer. It takes two arguments: the object itself and the property name as a string.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const myObj = { age: 30 };
const descriptor = Object.getOwnPropertyDescriptor(myObj, &apos;age&apos;);

console.log(descriptor); // Output: { value: 30, writable: true, enumerable: true, configurable: true }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, the &lt;code&gt;descriptor&lt;/code&gt; object shows the default attributes: &lt;code&gt;value&lt;/code&gt;, &lt;code&gt;writable&lt;/code&gt;, &lt;code&gt;enumerable&lt;/code&gt;, and &lt;code&gt;configurable&lt;/code&gt;. No surprises, everything is set to &lt;code&gt;true&lt;/code&gt; by default! 🎉&lt;/p&gt;
&lt;h3&gt;2. Defining Descriptors with &lt;code&gt;Object.defineProperty()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Okay, ready to step it up? What if you want to create a property with custom attributes? Say hello to &lt;code&gt;Object.defineProperty()&lt;/code&gt;. It takes three arguments: the object, the property name, and the descriptor object.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const person = {};
Object.defineProperty(
    person,
    &apos;name&apos;,
    {
        value: &apos;Alice&apos;,
        writable: false,
        enumerable: true,
        configurable: false
    }
);

console.log(person.name); // Output: Alice
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, &lt;a href=&quot;http://person.name&quot;&gt;&lt;code&gt;person.name&lt;/code&gt;&lt;/a&gt; is read-only and not configurable but still enumerable. Try changing its value, and JavaScript will be like, &quot;Nice try, buddy!&quot; 🤨&lt;/p&gt;
&lt;h3&gt;3. Batch Operation with &lt;code&gt;Object.defineProperties()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;But wait, there&apos;s more! What if you want to define multiple properties at once? &lt;code&gt;Object.defineProperties()&lt;/code&gt; has got your back.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const animal = {};
Object.defineProperties(animal, {
    name: {
        value: &apos;Dog&apos;,
        writable: true
    },
    sound: {
        value: &apos;Woof&apos;,
        enumerable: false
    }
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, &lt;code&gt;animal&lt;/code&gt; gets two properties, each with its own set of descriptors. Efficient, isn&apos;t it? 🤓&lt;/p&gt;
&lt;h3&gt;4. Computed property with &lt;code&gt;Object.defineProperty()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;But wait, there&apos;s more again. What if you want to define a property that depends on other ones? &lt;code&gt;Object.defineProperty()&lt;/code&gt; has got your back again.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const person = {
  firstName: &apos;John&apos;,
  lastName: &apos;Doe&apos;,
};

// Define a read-only property
Object.defineProperty(person, &apos;fullName&apos;, {
  get() {
    return `${this.firstName} ${this.lastName}`;
  },
  enumerable: true,
});

console.log(person.fullName); // John Doe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here &lt;code&gt;person&lt;/code&gt; has three properties, &lt;code&gt;firstName&lt;/code&gt;, &lt;code&gt;lastName&lt;/code&gt; and &lt;code&gt;fullName&lt;/code&gt;. &lt;code&gt;fullName&lt;/code&gt; depends on the others and it&apos;s enumerable so that it&apos;s included in the &lt;code&gt;for...in&lt;/code&gt; loop and &lt;code&gt;Object.keys()&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;Ok, I think the idea now it&apos;s clear and you can use your imagination to combine these configurations to provide the best descriptors for your objects.&lt;/p&gt;
&lt;p&gt;To find out more don&apos;t waste my YouTube video on my &lt;a href=&quot;https://www.youtube.com/@Puppo_92&quot;&gt;YouTube Channel&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=AHLdUs8LtIA&quot;&gt;https://www.youtube.com/watch?v=AHLdUs8LtIA&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In conclusion, Object Property Descriptors are a powerful feature of JavaScript that allows you to manipulate and define object properties with fine-grained control. This advanced feature offers developers the ability to create more dynamic and flexible code.&lt;/p&gt;
&lt;p&gt;Whether you&apos;re a junior developer or an expert, understanding Object Property Descriptors can help you level up your JavaScript skills.&lt;/p&gt;
&lt;p&gt;So go ahead, tinker with your code, challenge the norms, and keep pushing the boundaries. The JavaScript universe is your playground! 🚀&lt;/p&gt;
&lt;p&gt;You can find the code of this article &lt;a href=&quot;https://github.com/Puppo/javascript-you-dont-know/tree/07-object-descriptor&quot;&gt;in the GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>object</category><category>descriptor</category><category>js</category><category>Objects</category></item><item><title>JavaScript FinalizationRegistry Unraveled: Memory Management Magic Explained!</title><link>https://delpuppo.net/blog/javascript-you-dont-know/javascript-finalizationregistry-unraveled-memory-management-magic-explained/</link><guid isPermaLink="true">https://delpuppo.net/blog/javascript-you-dont-know/javascript-finalizationregistry-unraveled-memory-management-magic-explained/</guid><description>Introduction JavaScript&apos;s memory management can be tricky, especially when it comes to...</description><pubDate>Wed, 25 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;JavaScript&apos;s memory management can be tricky, especially when it comes to handling objects that are no longer needed. As developers, we often need to deal with memory leaks and other issues that arise from improper garbage collection. Fortunately, JavaScript has introduced a new feature called the FinalizationRegistry to help us manage memory more efficiently. In this blog post, we&apos;ll dive deep into the world of FinalizationRegistry, exploring its purpose, how to use it, and real-world scenarios where it can come in handy.&lt;/p&gt;
&lt;h2&gt;A Simple Example&lt;/h2&gt;
&lt;p&gt;To begin, let&apos;s take a look at a simple example to understand how FinalizationRegistry works. The FinalizationRegistry is an object that enables you to register a callback function that will be invoked when an object is garbage collected. Here&apos;s a basic example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const registry = new FinalizationRegistry((heldValue) =&amp;gt; {
  console.log(`Clean up: ${heldValue}`);
});

function createObject() {
  const obj = {id: 1};
  registry.register(obj, &quot;Object 1&quot;);
}

createObject();
// After some time, when the object is garbage collected, the console will log: &quot;Clean up: Object 1&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, we create a new FinalizationRegistry and provide a callback function that logs a message when the registered object is garbage collected. We then create an object and register it with the registry.&lt;/p&gt;
&lt;h2&gt;Real-World Scenario&lt;/h2&gt;
&lt;p&gt;Now, let&apos;s explore a more realistic scenario where FinalizationRegistry can be beneficial. Imagine we have a web application that allows users to upload and manipulate images. We use a third-party library to handle the image manipulation, and this library creates large objects that consume a significant amount of memory. To prevent memory leaks, we can use FinalizationRegistry to ensure that these objects are properly cleaned up when they are no longer needed.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const imageRegistry = new FinalizationRegistry((imageData) =&amp;gt; {
  console.log(`Cleaning up image data: ${imageData}`);
  // Perform additional cleanup tasks, such as releasing resources associated with imageData
});

function loadImage(imageUrl) {
  return fetch(imageUrl)
    .then((response) =&amp;gt; response.blob())
    .then((imageBlob) =&amp;gt; {
      const imageData = new ImageData(imageBlob);
      imageRegistry.register(imageData, `Image: ${imageUrl}`);
      return imageData;
    });
}

function manipulateImage(imageData) {
  // Use the third-party library to manipulate the image
}

loadImage(&apos;https://example.com/image.jpg&apos;)
  .then((imageData) =&amp;gt; {
    manipulateImage(imageData);
    // After manipulation, the imageData object will eventually be garbage collected
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, we create an imageRegistry using FinalizationRegistry and register the ImageData objects when they are loaded. When an ImageData object is garbage collected, the provided callback function will log a message and perform any additional cleanup tasks required.&lt;/p&gt;
&lt;h2&gt;Considerations&lt;/h2&gt;
&lt;p&gt;While the FinalizationRegistry is a powerful tool for managing memory, there are some important considerations to keep in mind:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The timing of garbage collection is not guaranteed, and the callback function may not be invoked immediately after an object becomes unreachable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;FinalizationRegistry should not be used to manage critical resources, as it only provides a best-effort cleanup mechanism.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The held values in the registry should not be used to access the registered objects, as it may prevent them from being garbage collected.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To find out more don&apos;t waste my YouTube video on my &lt;a href=&quot;https://www.youtube.com/@Puppo_92&quot;&gt;YouTube channel&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=3sgIFrjA61U&quot;&gt;https://www.youtube.com/watch?v=3sgIFrjA61U&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The JavaScript FinalizationRegistry is a valuable addition to the language that can help developers manage memory more efficiently and prevent memory leaks. By understanding how it works and knowing when to use it, you can create more performant and memory-efficient applications. Keep in mind the considerations mentioned above, and happy coding!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this article&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/javascript-you-dont-know/tree/06-finalizationregistry&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>memory</category><category>leak</category><category>js</category><category>FinalizationRegistry</category></item><item><title>Unlocking the Power of Proxies: JavaScript&apos;s Secret Superheroes</title><link>https://delpuppo.net/blog/javascript-you-dont-know/unlocking-the-power-of-proxies-javascripts-secret-superheroes/</link><guid isPermaLink="true">https://delpuppo.net/blog/javascript-you-dont-know/unlocking-the-power-of-proxies-javascripts-secret-superheroes/</guid><description>JavaScript&apos;s Proxy object is a powerful feature that enables you to intercept and customize...</description><pubDate>Wed, 18 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;JavaScript&apos;s Proxy object is a powerful feature that enables you to intercept and customize operations performed on objects. This versatile tool allows developers to create more efficient and flexible code while also improving code maintainability. In this article, we will dive into the world of JavaScript proxies, explore their use cases, and provide examples for expert developers.&lt;/p&gt;
&lt;h2&gt;A Brief Introduction to Proxies in JavaScript&lt;/h2&gt;
&lt;p&gt;A Proxy object in JavaScript is used to define custom behaviour for fundamental operations such as property lookup, assignment, enumeration, and function invocation. It acts as a wrapper around another object, called the target, and allows you to intercept and manipulate operations performed on the target object.&lt;/p&gt;
&lt;h3&gt;Creating a JavaScript Proxy&lt;/h3&gt;
&lt;p&gt;To create a JavaScript Proxy, you need two things: a target object and a handler object. The target object is the object you want to wrap with the Proxy, while the handler object defines the custom behaviour for the proxy.&lt;/p&gt;
&lt;p&gt;Here&apos;s a simple example of creating a Proxy:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const target = { name: &quot;John&quot;, surname: &quot;Doe&quot;, fullName: &quot;John Doe&quot; };
const handler = {
  get(_target, prop) {
    return _target[prop] ? _target[prop].toUpperCase() : &quot;Property not found&quot;;
  },
  set(_target, prop, value) {
    if (prop === &apos;name&apos;) {
      _target.fullName = value + &apos; &apos; + _target.surname;
    }
    if (prop === &apos;surname&apos;) {
      _target.fullName = _target.name + &apos; &apos; + value;
    }
    if (prop === &apos;fullName&apos;) {
      throw new Error(&apos;fullName is not writable&apos;)
    }
    _target[prop] = value;
    return true;
  }
};

const proxy = new Proxy(target, handler);
console.log(proxy.fullName); // Output: &quot;JOHN DOE&quot;
console.log(proxy.nonexistent); // Output: &quot;Property not found&quot;
proxy.name = &apos;Jane&apos;;
console.log(proxy.fullName); // Output: &quot;Jane Doe&quot;
proxy.surname = &apos;Smith&apos;;
console.log(proxy.fullName); // Output: &quot;Jane Smith&quot;
proxy.fullName = &apos;Tom Smith&apos;; // Error: fullName is not writable
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, we defined a &lt;code&gt;get&lt;/code&gt; trap in the handler object, which intercepts the property lookup operation on the target object. When a property is accessed on the proxy object, the &lt;code&gt;get&lt;/code&gt; trap is invoked, and it returns the property value in uppercase if the property exists or a custom message if it doesn&apos;t.&lt;br /&gt;
Then, we defined a &lt;code&gt;set&lt;/code&gt; trap, which intercepts a property&apos;s set. If the property name is &lt;code&gt;name&lt;/code&gt; or &lt;code&gt;surname&lt;/code&gt; calculates the &lt;code&gt;fullName&lt;/code&gt; and sets the target object with the right value, but if you try to set the &lt;code&gt;fullName&lt;/code&gt; property the code raises an error.&lt;/p&gt;
&lt;h3&gt;Use Cases for Proxies in JavaScript&lt;/h3&gt;
&lt;h4&gt;Validation and Constraints&lt;/h4&gt;
&lt;p&gt;Proxies can be used to enforce data validation and constraints when setting properties on an object. For example, you can ensure that a property value is a certain type or within a specific range.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const target = { age: 25 };
const handler = {
  set(_target, prop, value) {
    if (prop === &quot;age&quot; &amp;amp;&amp;amp; (typeof value !== &quot;number&quot; || value &amp;lt; 0 || value &amp;gt; 150)) {
      throw new TypeError(&quot;Invalid age value&quot;);
    }
    _target[prop] = value;
    return true;
  },
};

const proxy = new Proxy(target, handler);
proxy.age = 30; // Works fine
proxy.age = &quot;thirty&quot;; // Throws TypeError: &quot;Invalid age value&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Logging and Profiling&lt;/h4&gt;
&lt;p&gt;Proxies can be used to log and profile operations performed on an object, which can be helpful during debugging and performance analysis.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const target = { message: &quot;Hello, World!&quot; };
const handler = {
  get(_target, prop) {
    console.log(`Accessing property &quot;${prop}&quot;`);
    return _target[prop];
  },
  set(_target, prop, value) {
    console.log(`Setting property &quot;${prop}&quot; to &quot;${value}&quot;`);
    _target[prop] = value;
    return true;
  },
};

const proxy = new Proxy(target, handler);
console.log(proxy.message); // Logs: &quot;Accessing property &quot;message&quot;&quot; and outputs: &quot;Hello, World!&quot;
proxy.message = &quot;Goodbye, World!&quot;; // Logs: &quot;Setting property &quot;message&quot; to &quot;Goodbye, World!&quot;&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To learn more don&apos;t miss my YouTube video about JavaScript Proxy on my &lt;a href=&quot;https://www.youtube.com/@Puppo_92&quot;&gt;YouTube channel&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=e7_lxSrP_Ok&quot;&gt;https://www.youtube.com/watch?v=e7_lxSrP_Ok&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;JavaScript&apos;s Proxy object is a powerful and versatile feature that allows developers to create more efficient and flexible code. By understanding and utilizing proxies, you can unlock their full potential and become a true JavaScript superhero.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this article&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/javascript-you-dont-know/tree/05-proxies&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>es6</category><category>proxy</category><category>proxies</category><category>js</category></item><item><title>JavaScript WeakRef Explained: Harnessing Memory Management Magic</title><link>https://delpuppo.net/blog/javascript-you-dont-know/javascript-weakref-explained-harnessing-memory-management-magic/</link><guid isPermaLink="true">https://delpuppo.net/blog/javascript-you-dont-know/javascript-weakref-explained-harnessing-memory-management-magic/</guid><description>Introduction to WeakRef WeakRef is a powerful feature in JavaScript that allows developers...</description><pubDate>Wed, 11 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction to WeakRef&lt;/h2&gt;
&lt;p&gt;WeakRef is a powerful feature in JavaScript that allows developers to create weak object references. A weak reference is a reference that does not prevent the object it refers to from being garbage collected. This can be useful when you want to maintain a reference to an object without preventing it from being cleaned up by the garbage collector.&lt;/p&gt;
&lt;h2&gt;How WeakRef Works&lt;/h2&gt;
&lt;p&gt;WeakRef works by creating a weak reference to an object. This reference does not count towards the object&apos;s reference count and does not prevent it from being garbage collected. To access the object, you can call the &lt;code&gt;deref()&lt;/code&gt; method on the WeakRef instance. If the object is still alive, the method will return the object; otherwise, it will return undefined.&lt;/p&gt;
&lt;h2&gt;Implementing WeakRef in Your Code&lt;/h2&gt;
&lt;p&gt;To use WeakRef in your code, follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a new WeakRef instance by passing the object you want to reference as an argument: &lt;code&gt;const weakRef = new WeakRef(targetObject);&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To access the object, call the &lt;code&gt;deref()&lt;/code&gt; method on the WeakRef instance: &lt;code&gt;const object = weakRef.deref();&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Check if the object is still alive by testing if it is not undefined: &lt;code&gt;if (object !== undefined) { /* object is still alive */ }&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Use Cases for WeakRef&lt;/h2&gt;
&lt;p&gt;WeakRef can be helpful in several scenarios, such as:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Caching&lt;/strong&gt;:
Use WeakRef to create a cache for expensive-to-create objects. When an object is no longer needed, it can be garbage collected automatically, freeing up memory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DOM Element References&lt;/strong&gt;:
In web applications, you can use WeakRef to hold references to DOM elements. This can help prevent memory leaks when you need to keep track of elements for event handling or manipulation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Resource Cleanup&lt;/strong&gt;:
When working with external resources like files or network connections, you can use WeakRef to keep track of those resources. If the resource becomes unused (e.g., a file is closed or a network connection is no longer needed), it can be automatically released.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Memoization&lt;/strong&gt;:
Implement memoization using WeakRef to store the results of function calls. This allows you to cache function results without preventing the input arguments from being garbage-collected when they&apos;re no longer needed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Managing Timers&lt;/strong&gt;:
When using timers (e.g., setTimeout or setInterval), you can use WeakRef to hold references to objects associated with the timer. This can help ensure that the timer doesn&apos;t keep objects alive longer than necessary.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Event Handling&lt;/strong&gt;:
In event-driven applications, you can use WeakRef to manage event listeners. When an object with event listeners is no longer in use, the associated event listeners can be automatically removed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Reacting to DOM Node Removal&lt;/strong&gt;:
In cases where you want to perform actions when DOM nodes are removed, you can use WeakRef to track DOM nodes. When a node is removed from the DOM, you can receive a notification and perform cleanup tasks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Custom Data Structures&lt;/strong&gt;:
Create custom data structures that use WeakRef to hold references to elements. This can be particularly useful in scenarios like implementing caches or data structures with automatic cleanup.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Managing Web Workers&lt;/strong&gt;:
When working with Web Workers, you can use WeakRef to manage references to worker instances. When a worker is no longer needed, its reference can be automatically released.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Optimizing Memory-Intensive Applications&lt;/strong&gt;:
In memory-intensive applications, you can use WeakRef to ensure that large data structures or objects are only kept in memory as long as they&apos;re actively used.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Best Practices and Limitations&lt;/h2&gt;
&lt;p&gt;When using WeakRef, keep in mind the following best practices and limitations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Use WeakRef only when necessary, as it can introduce complexity and potential performance issues.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Do not rely on the timing of garbage collection, as it may vary across JavaScript engines and environments.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Be aware that WeakRef is not supported in all environments, so you may need to provide a fallback implementation or polyfill.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you want to learn more about WeakRef, don&apos;t miss out on my YouTube video on &lt;a href=&quot;https://www.youtube.com/@Puppo_92&quot;&gt;my YouTube channel&lt;/a&gt; 🚀&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://youtu.be/-rN03KAHGC4&quot;&gt;https://youtu.be/-rN03KAHGC4&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;WeakRef is a powerful feature in JavaScript that allows you to create weak references to objects, enabling you to maintain references without preventing garbage collection. By understanding how WeakRef works and its use cases, you can use memory more efficiently in your applications and avoid memory leaks.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Puppo/javascript-you-dont-know/tree/04-weakrefs&quot;&gt;&lt;em&gt;Here is&lt;/em&gt;&lt;/a&gt; &lt;em&gt;the source code of this post.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>es6</category><category>weakref</category><category>weakrefs</category><category>js</category></item><item><title>Unlock the Power of JavaScript WeakSet: Mastering a Hidden Gem!</title><link>https://delpuppo.net/blog/javascript-you-dont-know/unlock-the-power-of-javascript-weakset-mastering-a-hidden-gem/</link><guid isPermaLink="true">https://delpuppo.net/blog/javascript-you-dont-know/unlock-the-power-of-javascript-weakset-mastering-a-hidden-gem/</guid><description>In the vast landscape of JavaScript, many powerful features often go unnoticed. One such hidden gem...</description><pubDate>Wed, 04 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the vast landscape of JavaScript, many powerful features often go unnoticed. One such hidden gem is the WeakSet, an unsung hero of the language that can help you optimize your code and manage memory more effectively. In this article, we&apos;ll dive deep into WeakSet, uncovering their potential and learning how to use them effectively in our JavaScript projects.&lt;/p&gt;
&lt;h2&gt;A Brief Introduction to WeakSet&lt;/h2&gt;
&lt;p&gt;WeakSet is a collection of objects similar to the more commonly used Set.&lt;br /&gt;
However, there&apos;s a significant difference between the two: WeakSet holds only weak references to the objects stored within them. This means that if an object is only referenced by a WeakSet, it can still be garbage collected, freeing up valuable memory resources.&lt;/p&gt;
&lt;p&gt;This unique feature of WeakSet makes it an excellent choice for managing certain types of data relationships, mainly when memory management is a priority.&lt;/p&gt;
&lt;h2&gt;Creating and Using WeakSet&lt;/h2&gt;
&lt;p&gt;To create a WeakSet, instantiate a new instance of the WeakSet class:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const weakSet = new WeakSet();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Adding objects to a WeakSet is easy. Just use the &lt;code&gt;add&lt;/code&gt; method:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const obj1 = {};
const obj2 = {};

weakSet.add(obj1);
weakSet.add(obj2);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;WeakSets also provide methods for checking if an object is present (&lt;code&gt;has&lt;/code&gt;) and removing objects (&lt;code&gt;delete&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;console.log(weakSet.has(obj1)); // true
weakSet.delete(obj1);
console.log(weakSet.has(obj1)); // false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, unlike Sets, WeakSets do not have methods for iterating over their contents or determining their size. This is because of their weakly-referenced nature, which makes it impossible to know how many objects are still being held in memory.&lt;/p&gt;
&lt;h2&gt;Use Cases for WeakSets&lt;/h2&gt;
&lt;h3&gt;1. Managing DOM Elements&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;WeakSet&lt;/code&gt; can be incredibly useful when working with the DOM. You can store references to DOM elements without worrying about memory leaks. When an element is removed from the DOM, the reference in the &lt;code&gt;WeakSet&lt;/code&gt; will be automatically garbage collected.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const domElements = new WeakSet();
const element = document.querySelector(&apos;.my-element&apos;);
domElements.add(element);

// Later, when the element is removed from the DOM
domElements.has(element); // false (garbage collected)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. Private Data Storage&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;WeakSet&lt;/code&gt; can be used to store private data associated with an object without exposing it. Since the references are weak, the data will be automatically removed when the object is no longer reachable.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const privateData = new WeakSet();

class MyClass {
  constructor() {
    privateData.add(this);
  }

  #data = &apos;I am private data&apos;;

  getData() {
    if (privateData.has(this)) {
      return this.#data;
    }
    return undefined;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To see WeakSets in action, don&apos;t waste the opportunity to look at my YouTube video about them.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://youtu.be/m3BKqgeVAa4&quot;&gt;https://youtu.be/m3BKqgeVAa4&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;In Conclusion&lt;/h2&gt;
&lt;p&gt;WeakSet may not be the most well-known feature of JavaScript, but it offers unique capabilities that can be invaluable in certain situations. By understanding and embracing WeakSet, you can optimize your code, enhance memory management, and unlock the full potential of this hidden gem in the JavaScript universe.&lt;/p&gt;
&lt;p&gt;You can find the source code &lt;a href=&quot;https://github.com/Puppo/javascript-you-dont-know/tree/03-weaksets&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>es6</category><category>weakset</category><category>weaksets</category><category>es2015</category><category>js</category></item><item><title>Unlocking JavaScript&apos;s Secret Weapon: The Power of WeakMaps</title><link>https://delpuppo.net/blog/javascript-you-dont-know/unlocking-javascripts-secret-weapon-the-power-of-weakmaps/</link><guid isPermaLink="true">https://delpuppo.net/blog/javascript-you-dont-know/unlocking-javascripts-secret-weapon-the-power-of-weakmaps/</guid><description>Introduction JavaScript is a powerful and versatile programming language that has evolved...</description><pubDate>Wed, 27 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;JavaScript is a powerful and versatile programming language that has evolved over the years, introducing new features and improvements to enhance its performance and capabilities. One such feature is the WeakMap, a collection of key-value pairs that offers unique benefits regarding memory management and data privacy. This article will delve into the world of WeakMap in JavaScript, exploring their creation, usage, limitations, and real-world applications.&lt;/p&gt;
&lt;h2&gt;Understanding WeakMap&lt;/h2&gt;
&lt;p&gt;In JavaScript, a WeakMap is a type of Map that holds key-value pairs where the keys are objects, and the values can be any arbitrary data. The primary difference between a Map and a WeakMap is how they manage memory management. In a WeakMap, when a key object becomes inaccessible, the entry is automatically removed, allowing the garbage collector to reclaim memory efficiently.&lt;/p&gt;
&lt;h2&gt;Creating and Using WeakMap&lt;/h2&gt;
&lt;p&gt;To create a new WeakMap, use the &lt;code&gt;new WeakMap()&lt;/code&gt; constructor. Once created, you can set values for the keys using the &lt;code&gt;set&lt;/code&gt; method, as shown below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const weakmap = new WeakMap();
const key = { name: &quot;John Doe&quot; };
weakmap.set(key, &quot;Some value&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To retrieve values associated with keys, use the &lt;code&gt;get&lt;/code&gt; method:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const value = weakmap.get(key); // &quot;Some value&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can remove entries from the WeakMap using the &lt;code&gt;delete&lt;/code&gt; method and check for the existence of a key using the &lt;code&gt;has&lt;/code&gt; method:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;weakmap.delete(key); // true
weakmap.has(key); // false
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Practical Applications of WeakMap&lt;/h2&gt;
&lt;p&gt;WeakMap offers several practical applications in JavaScript:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Privacy and Encapsulation: By storing private data separately from the object, WeakMap can enhance privacy and encapsulation. This is particularly useful for classes and objects where internal data should not be exposed to the outside world.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Memory Management: WeakMap automatically releases unreferenced keys and associated values, allowing for efficient memory management in large applications.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Caching: WeakMap can implement caching mechanisms without causing memory leaks, as they automatically remove entries when keys are no longer accessible.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Limitations of WeakMap&lt;/h2&gt;
&lt;p&gt;Despite their benefits, WeakMap has some limitations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Keys must be objects: Unlike Maps, WeakMap requires keys to be objects, not primitive values.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No built-in iteration methods: WeakMap does not have built-in methods for iterating over their entries, such as &lt;code&gt;forEach&lt;/code&gt; or &lt;code&gt;entries&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No &lt;code&gt;clear&lt;/code&gt; method: There is no built-in method to clear the entire WeakMap.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Limited compatibility: WeakMap is not supported in some older browsers, limiting their compatibility.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Real-world Examples and Use Cases&lt;/h2&gt;
&lt;p&gt;WeakMap can be utilized in various real-world scenarios:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Event Listeners: When managing event listeners in DOM elements, WeakMap can help prevent memory leaks by automatically removing entries when elements are no longer accessible.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Private Data Storage: WeakMap can store private data in classes and objects, ensuring that internal data is not exposed to the outside world.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Large Applications: WeakMap can optimize memory usage in large applications by automatically releasing unreferenced data, improving performance and reducing memory leaks.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;To find out more about WeakMap don&apos;t miss out on my Youtube video on my&lt;/em&gt; &lt;a href=&quot;https://www.youtube.com/@puppo_92&quot;&gt;&lt;em&gt;Youtube channel&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://youtu.be/8Z4ZYDSxN3A&quot;&gt;https://youtu.be/8Z4ZYDSxN3A&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In conclusion, WeakMap offers powerful features and applications for efficient memory management and data privacy in JavaScript. While they have some limitations, their benefits often outweigh these drawbacks, making them a valuable addition to a JavaScript developer&apos;s toolkit. As the language continues to evolve, future developments will likely address these limitations and further improve the usefulness of WeakMap in JavaScript applications.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The code of this article is available&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/javascript-you-dont-know/tree/02-weakmaps&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>es6</category><category>weakmap</category></item><item><title>Unveiling the Magic: Exploring JavaScript Symbols</title><link>https://delpuppo.net/blog/javascript-you-dont-know/unveiling-the-magic-exploring-javascript-symbols/</link><guid isPermaLink="true">https://delpuppo.net/blog/javascript-you-dont-know/unveiling-the-magic-exploring-javascript-symbols/</guid><description>Introduction to JavaScript Symbols JavaScript Symbols are a new primitive data type...</description><pubDate>Wed, 20 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction to JavaScript Symbols&lt;/h2&gt;
&lt;p&gt;JavaScript Symbols are a new primitive data type introduced in ECMAScript 6 (ES6). They are used as unique, non-string identifiers for object properties, useful in avoiding naming collisions and enabling more advanced programming techniques.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://youtu.be/o8YDHAS-fo0&quot;&gt;https://youtu.be/o8YDHAS-fo0&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Creating and Understanding Symbols&lt;/h2&gt;
&lt;p&gt;Symbols are created using the &lt;code&gt;Symbol()&lt;/code&gt; function, which can take an optional description as an argument. Each symbol is unique; even if two symbols have the same description, they are considered distinct.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const propSymbol = Symbol(&quot;propName&quot;);
const propSymbol2 = Symbol(&quot;propName&quot;);

propSymbol === propSymbol2 // false
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Unique Identifiers and Property Keys&lt;/h2&gt;
&lt;p&gt;Symbols are often used as property keys in objects to ensure uniqueness and prevent naming collisions. They can be used alongside string keys without conflict, and their uniqueness makes them ideal for use as metadata or private properties in objects.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const propSymbol = Symbol(&quot;propName&quot;);
const propSymbol2 = Symbol(&quot;propName&quot;);

const obj = {
  [propSymbol]: &quot;propSymbol&quot;,
  [propSymbol2]: &quot;propSymbol2&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;The Global Symbol Registry&lt;/h2&gt;
&lt;p&gt;The global Symbol registry allows you to create and share symbols across different scopes and realms. To create a global symbol, use &lt;code&gt;Symbol.for(key)&lt;/code&gt;, which takes a string as its argument. This method checks if a symbol with the same key exists in the registry; if not, it creates a new one.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// my-module-1.js
export const propSymbol = Symbol(&quot;propName&quot;);
export const propSymbolShare = Symbol.for(&quot;propName&quot;);

// my-module-2.js
export const propSymbol = Symbol(&quot;propName&quot;);
export const propSymbolShare = Symbol.for(&quot;propName&quot;);

// index.js
import { propSymbol as propSymbolM1, propSymbolShare as propSymbolShareM1 } from &apos;./my-module.js&apos;
import { propSymbol as propSymbolM2, propSymbolShare as propSymbolShareM2 } from &apos;./my-module-2.js&apos;

console.log(propSymbolM1 === propSymbolM2); // false

console.log(propSymbolM1 === propSymbolShareM1); // false
console.log(propSymbolM2 === propSymbolShareM2); // false

console.log(propSymbolShareM1 === propSymbolShareM2); // true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&apos;s also possible to retrieve the key of a Symbol using &lt;code&gt;Symbol.keyFor(key)&lt;/code&gt; but only for shared keys.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export const propSymbol = Symbol(&quot;propName&quot;);
export const propSymbolShare = Symbol.for(&quot;propName&quot;);

console.log(Symbol.keyFor(propSymbol)); // undefined
console.log(Symbol.keyFor(propSymbolShare)); // propName
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Symbols and Iteration&lt;/h2&gt;
&lt;p&gt;Symbols are not enumerable, which means they are not included in standard iteration methods like &lt;code&gt;for...in&lt;/code&gt; loops or &lt;code&gt;Object.keys()&lt;/code&gt;. To access an object&apos;s symbol properties, use &lt;code&gt;Object.getOwnPropertySymbols()&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const propSymbol = Symbol(&quot;propName&quot;);
const propSymbol2 = Symbol(&quot;propName&quot;);

const obj = {
  [propSymbol]: &quot;propSymbol&quot;,
  [propSymbol2]: &quot;propSymbol2&quot;
}
console.log(JSON.stringify(obj)); // {}
console.log(Object.keys(obj)); // []
console.log(Object.getOwnPropertyNames(obj)); // []
for (const key in obj) {
  console.log(key); // nothing
}

console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(propName), Symbol(propName)]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Well-Known Symbols in JavaScript&lt;/h2&gt;
&lt;p&gt;Well-known symbols are predefined global symbols that represent common behaviours in JavaScript, such as &lt;code&gt;Symbol.iterator&lt;/code&gt;, &lt;code&gt;Symbol.asyncIterator&lt;/code&gt;, &lt;code&gt;Symbol.toStringTag&lt;/code&gt;, and &lt;code&gt;Symbol.species&lt;/code&gt;. These symbols can be used to customize the behaviour of built-in JavaScript objects and classes.&lt;/p&gt;
&lt;h2&gt;Use Cases and Practical Applications&lt;/h2&gt;
&lt;p&gt;Symbols can be used to implement private properties, metadata, or methods, avoiding naming collisions in libraries and frameworks. They are also used to customize the behaviour of well-known JavaScript objects and classes, such as iterators and string conversion.&lt;/p&gt;
&lt;h2&gt;Limitations and Considerations&lt;/h2&gt;
&lt;p&gt;Symbols are not supported in older JavaScript environments, and their unique nature may require additional care when working with serialization or proxy objects. Additionally, they are not directly accessible during iteration, which may require extra steps to access their properties.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;JavaScript Symbols provide a powerful, unique identifier for object properties, helping to avoid naming collisions and enabling advanced programming techniques. Understanding their use cases and limitations is essential for modern JavaScript developers.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the source code&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/javascript-you-dont-know/tree/01-symbols&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>es6</category><category>symbols</category><category>js</category></item><item><title>JavaScript Async Generators Unleashed: Harnessing Asynchronous Power</title><link>https://delpuppo.net/blog/js-iterators-generators/javascript-async-generators-unleashed-harnessing-asynchronous-power/</link><guid isPermaLink="true">https://delpuppo.net/blog/js-iterators-generators/javascript-async-generators-unleashed-harnessing-asynchronous-power/</guid><description>In the dynamic realm of JavaScript, the ability to efficiently handle asynchronous operations is...</description><pubDate>Fri, 15 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the dynamic realm of JavaScript, the ability to efficiently handle asynchronous operations is paramount for building responsive and robust applications. While Async Iterators have already proven their worth in managing asynchronous data streams, JavaScript takes another leap forward with Async Generators. Imagine a world where you can effortlessly produce a continuous stream of asynchronous data while dynamically controlling its flow. This is precisely where Async Generators excel, revolutionizing the way we handle and manipulate asynchronous sequences.&lt;/p&gt;
&lt;p&gt;In this blog post, we&apos;re diving deep into the captivating world of JavaScript Async Generators. We&apos;ll unveil how Async Generators empower developers to create elegant solutions for complex asynchronous scenarios. Whether you&apos;re grappling with real-time data synchronization, asynchronous data processing, or any scenario demanding fine-tuned control over data flow, join us on this journey as we unravel the capabilities, nuances, and transformative power of JavaScript Async Generators.&lt;/p&gt;
&lt;p&gt;Before we delve into Async Generators, let&apos;s recap the basics of asynchronous programming. In JavaScript, asynchronous tasks are crucial for handling time-consuming operations without blocking the main thread. Functions like setTimeout, AJAX requests, and Promises have become commonplace in managing asynchronous operations.&lt;/p&gt;
&lt;p&gt;Generators, denoted by &lt;code&gt;function*&lt;/code&gt; syntax, are a powerful feature introduced in ES6. They allow us to pause and resume the execution of a function, providing a valuable mechanism for lazy evaluation. The &lt;code&gt;yield&lt;/code&gt; keyword within a generator function lets us yield values individually, pausing the function&apos;s execution until the next value is requested. If you want to learn more, there is relative content about them in this series.&lt;/p&gt;
&lt;p&gt;Now, imagine combining the magic of asynchronous operations with the versatility of generators. Enter Async Generators! These supercharged functions enable us to work with asynchronous data streams more intuitively and elegantly.&lt;/p&gt;
&lt;p&gt;An async generator function is declared using &lt;code&gt;async function*&lt;/code&gt; syntax. Inside, the &lt;code&gt;yield&lt;/code&gt; keyword can be combined with &lt;code&gt;await&lt;/code&gt; to handle asynchronous operations gracefully. This means we can yield promises, fetch data and seamlessly integrate it into our data stream.&lt;/p&gt;
&lt;p&gt;The real beauty of async generators lies in their ability to simplify complex asynchronous tasks. They&apos;re particularly handy when dealing with data streams from sources like databases, APIs, or even real-time event streams. Imagine processing a continuous stream of sensor data or handling multiple concurrent requests without drowning in callback hell!&lt;/p&gt;
&lt;p&gt;Let&apos;s take a look at an example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;async function* getUsers(ids: number[]) {
  for (const id of ids) {
    console.log(&quot;getUsers next&quot;);
    const data = fetch(`https://reqres.in/api/users/${id}`).then(res =&amp;gt;
      res.json()
    );
    yield data;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using a &lt;code&gt;for-of&lt;/code&gt; loop, the function iterates over the IDs and fetches the data for every user on every iteration. However, using the yield, stop the execution and resume it only when the caller asks for the next value.&lt;br /&gt;
Like Async Iterators, also Async Generators can be iterated using a &lt;code&gt;for-await-of&lt;/code&gt; loop.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for await (const user of getUsers([1, 2, 3, 4, 5])) {
  console.log(user);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Error handling and completion are crucial aspects of asynchronous programming. With async generators, we can catch errors using try-catch blocks within the generator function. Plus, we can signal the end of data using the &apos;return&apos; statement, closing the loop on our data stream.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;try {
  for await (const user of getUsers([1, 2, 3, 4, 5])) {
    console.log(user);
  }
} catch (err) {
  console.error(err);
}

async function* getUsers(ids: number[]) {
  for (const id of ids) {
    console.log(&quot;getUsers next&quot;);
    const data = fetch(`https://reqres.in/api/users/${id}`).then(res =&amp;gt;
      res.json()
    );
    if (id &amp;gt; 4) return data; // &amp;lt;-- Return
    yield data;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Like Generators, also Async Generators can be combined. For instance, we can create an Async Generator &lt;code&gt;map&lt;/code&gt; function that accepts an Async Generator and a transformation function and returns a new async generator with the transformations.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;async function* map&amp;lt;T, U&amp;gt;(
  asyncIterable: AsyncIterable&amp;lt;T&amp;gt;,
  callback: (value: T) =&amp;gt; U
) {
  for await (const item of asyncIterable) {
    yield callback(item);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Asynchronous programming in JavaScript continues to evolve, and Async Generators are a testament to its dynamic nature. With their power to elegantly manage complex asynchronous tasks, async generators offer a glimpse into the future of streamlined coding. So, fellow developers, embrace this innovative tool and unlock new possibilities in your projects.&lt;/p&gt;
&lt;p&gt;I also created a video about Async Generators on my &lt;a href=&quot;https://www.youtube.com/@Puppo_92/&quot;&gt;Youtube channel&lt;/a&gt; and you can find it below.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://youtu.be/0uQvNZ8th08&quot;&gt;https://youtu.be/0uQvNZ8th08&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&apos;s a wrap for today&apos;s discussion on JavaScript Async Generators. I hope you found this exploration insightful and inspiring. Remember, staying curious and open to new concepts is the key to mastering your craft in the ever-evolving programming landscape.&lt;/p&gt;
&lt;p&gt;If you enjoyed this post, like and share it. And if you have questions, feedback or doubts let me know in the comments.&lt;/p&gt;
&lt;p&gt;Until next time, happy coding and thanks for reading 👩💻👨💻&lt;/p&gt;
&lt;p&gt;N.B. you can find the code of this post &lt;a href=&quot;https://github.com/Puppo/javascript-iterators-and-generators/tree/04-async-generators&quot;&gt;in the GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>generator</category><category>generators</category><category>async</category><category>js</category><category>asynchronous</category></item><item><title>Mastering JavaScript Async Iterators: Unlocking Asynchronous Magic</title><link>https://delpuppo.net/blog/js-iterators-generators/mastering-javascript-async-iterators-unlocking-asynchronous-magic/</link><guid isPermaLink="true">https://delpuppo.net/blog/js-iterators-generators/mastering-javascript-async-iterators-unlocking-asynchronous-magic/</guid><description>In the ever-evolving landscape of JavaScript, staying up-to-date with its latest features is crucial...</description><pubDate>Fri, 08 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the ever-evolving landscape of JavaScript, staying up-to-date with its latest features is crucial for writing efficient and modern code. One such feature that has garnered significant attention is the Async Iterator. While iterators have long been an integral part of JavaScript for sequential data processing, the introduction of asynchronous programming patterns brought about the need for asynchronous iteration.&lt;/p&gt;
&lt;p&gt;Imagine effortlessly traversing through data streams that might involve fetching data from APIs, reading from files, or any other asynchronous data source. This is precisely where Async Iterators shine, providing a seamless and elegant solution to handle such scenarios. In this blog post, we&apos;ll delve into the world of JavaScript Async Iterators, exploring their fundamentals, understanding their benefits, and uncovering how they can be a game-changer in writing robust asynchronous code. Whether you&apos;re a seasoned developer looking to expand your skill set or a newcomer curious about advanced JavaScript techniques, this blog post is for you. We will unravel the power of Async Iterators and take your asynchronous programming skills to new heights.&lt;/p&gt;
&lt;p&gt;Before we jump into the code, let&apos;s understand what async iterators are. In JavaScript, iterators are objects that allow us to loop over collections. Async iterators take this concept a step further by allowing us to handle asynchronous operations, like fetching data from APIs or reading from streams.&lt;/p&gt;
&lt;p&gt;Creating an async iterable is simple. We use the &lt;code&gt;Symbol.asyncIterator&lt;/code&gt; to define the async iterator method inside an object. This method will return an object with the &lt;code&gt;next&lt;/code&gt; method that resolves a promise containing the &lt;code&gt;next&lt;/code&gt; value in the asynchronous sequence.&lt;br /&gt;
Let&apos;s take a look at an example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const getUsers = (ids: number[]): AsyncIterable&amp;lt;User&amp;gt; =&amp;gt; {
  return {
    [Symbol.asyncIterator]() {
      let i = 0;
      return {
        async next() {
          console.log(&quot;getUsers next&quot;);
          if (i === ids.length) {
            return { done: true, value: null };
          }
          const data = await fetch(
            `https://reqres.in/api/users/${ids[i++]}`
          ).then(res =&amp;gt; res.json());
          return { done: false, value: data };
        },
      };
    },
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Imagine you have a list of IDs and want to read the user data only if needed. Using AsyncIterators, you can create a function that handles the API and returns the result of every request on every iteration, making the code more transparent.&lt;/p&gt;
&lt;p&gt;To consume the values of an async iterable, we use the &lt;code&gt;for-await-of&lt;/code&gt; loop. This loop works just like the regular &lt;code&gt;for-of&lt;/code&gt; loop, but it&apos;s designed specifically for asynchronous iterables.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for await (const user of getUsers([1, 2, 3, 4, 5])) {
  console.log(user);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Error handling is crucial when dealing with asynchronous operations. Async iterators allow us to handle errors using &lt;code&gt;try-catch&lt;/code&gt; blocks around the &lt;code&gt;for-await-of&lt;/code&gt; loop.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;try {
    for await (const user of getUsers([1, 2, 3, 4, 5])) {
      console.log(user);
    }
  } catch (err) {
    console.error(err);
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;AsyncIterator runs code only if needed, so until you don&apos;t call the next method, nothing happens, like for Iterators.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;return&lt;/code&gt; method exists also for AsyncIterators. This method is used in case the code doesn&apos;t complete all the iterations. Imagine the loop calls a break or a return; in this case, JavaScript under the hood calls the &lt;code&gt;return&lt;/code&gt; method for us. In this method, we can handle whatever we need. We may need to reset something or check the current value of the iterator.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const getUsers = (ids: number[]): AsyncIterable&amp;lt;User&amp;gt; =&amp;gt; {
  return {
    [Symbol.asyncIterator]() {
      let i = 0;
      return {
        ...
        async return() {
          console.log(&quot;getUsers return&quot;);
          return { done: true, value: null };
        },
      };
    },
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Async Iterators are powerful like Iterators, and we can create functions that accept an AsyncIterator and manipulate it to return another Async Iterator. For instance, we can create a map function that accepts an Async Iterator and returns another with a callback specified by the user.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function map&amp;lt;T, U&amp;gt;(iter: AsyncIterable&amp;lt;T&amp;gt;, fn: (v: T) =&amp;gt; U): AsyncIterable&amp;lt;U&amp;gt; {
  return {
    [Symbol.asyncIterator]() {
      const iterator = iter[Symbol.asyncIterator]();
      return {
        async next() {
          console.log(&quot;map next&quot;);
          const { done, value } = await iterator.next();
          if (done) return { done, value: null };
          return { done, value: fn(value) };
        },
        async return() {
          console.log(&quot;map return&quot;);
          if (iterator?.return) await iterator?.return();
          return { done: true, value: null };
        },
      };
    },
  };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These functions have all the benefits said before. Javascript does nothing until the codebase doesn&apos;t ask for the next function; the same is true for the &lt;code&gt;return&lt;/code&gt; method, and now you can compose the &lt;code&gt;getUsers&lt;/code&gt; with the &lt;code&gt;map&lt;/code&gt; to build a new Async Iterator.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const iterator = map(getUsers([1, 2, 3, 4, 5]), user =&amp;gt; user.data.id)
for await (const num of iterator) {
  if (num === 3) break;
  console.log(num);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And there you have it a deep dive into the world of asynchronous iterators in JavaScript. They provide an elegant solution to working with asynchronous data streams, making your code more organized and efficient. Experiment with async iterators in your projects, and you&apos;ll be amazed at how they simplify complex asynchronous workflows.&lt;/p&gt;
&lt;p&gt;I also created a video on my &lt;a href=&quot;https://www.youtube.com/@Puppo_92/&quot;&gt;Youtube channel&lt;/a&gt;, that you can find below.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://youtube.com/watch?v=0_mzZ9QOebg&quot;&gt;https://youtube.com/watch?v=0_mzZ9QOebg&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you found this content helpful, like and share it. And if you have any questions, feedback, or doubts, let me know in the comments 😀&lt;/p&gt;
&lt;p&gt;Thanks for reading! And Happy coding! 👩💻 👨💻&lt;/p&gt;
&lt;p&gt;N.B. you can find the code of this post &lt;a href=&quot;https://github.com/Puppo/javascript-iterators-and-generators/tree/03-async-iterators&quot;&gt;in the GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>iterators</category><category>async</category><category>asynchronous</category><category>iterator</category><category>js</category></item><item><title>Unleashing the Power: Demystifying JavaScript Generators</title><link>https://delpuppo.net/blog/js-iterators-generators/unleashing-the-power-demystifying-javascript-generators/</link><guid isPermaLink="true">https://delpuppo.net/blog/js-iterators-generators/unleashing-the-power-demystifying-javascript-generators/</guid><description>Welcome to this blog post, where we&apos;re diving into the fascinating world of JavaScript generators. If...</description><pubDate>Fri, 01 Sep 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome to this blog post, where we&apos;re diving into the fascinating world of JavaScript generators. If you&apos;re looking to take your coding skills to the next level and explore a powerful tool for managing operations, you&apos;ve come to the right place.&lt;/p&gt;
&lt;p&gt;In the fast-paced landscape of web development, managing tasks and handling complex flows of data can be quite challenging. This is where JavaScript generators come into play. These remarkable constructs introduce a new level of control and flexibility, allowing developers to write code that can be paused, resumed, and iterated step by step.&lt;/p&gt;
&lt;p&gt;In this blog post, we&apos;ll take you on a journey through the core concepts of JavaScript generators. We&apos;ll unravel their syntax, explore their capabilities, and showcase examples of how they can simplify your code and make it more manageable. By the end of this read, you&apos;ll not only understand the ins and outs of generators but also be equipped with the knowledge to start using them effectively in your own projects.&lt;/p&gt;
&lt;p&gt;Buckle up as we embark on this exploration of JavaScript generators, unravelling their potential and discovering how they can revolutionize the way you write code. Whether you&apos;re a seasoned developer or just starting with JavaScript, there&apos;s something valuable here for you. Let&apos;s begin!&lt;/p&gt;
&lt;p&gt;A generator in JavaScript is a function that, after the function keyword, has a &lt;code&gt;*&lt;/code&gt;. It&apos;s not possible to create generators in JavaScript using arrow functions. Generators are special functions that implement the Iterable interface very simply; you can learn more about them in this blog post. The particularity of generators is the &lt;code&gt;yield&lt;/code&gt; keyword. Using the &lt;code&gt;yield&lt;/code&gt;, we can return a new value to the iteration but without ending the function execution, simply putting it on pause, until the next request for the next value and until it&apos;s not completed.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function* range(start: number, end: number): Iterable&amp;lt;number&amp;gt; {
  let n = start;
  while (n &amp;lt;= end) {
    console.log(&quot;range next&quot;);
    yield n++;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, the range generator is a simple generator function, and it&apos;s understandable from the &lt;code&gt;*&lt;/code&gt; near-function keyword. Using a simple while, the function checks if the current value is less or equal to the end value and if true, using the &lt;code&gt;yield&lt;/code&gt; returns the value; else exists from the while and closes the generator. Like iterators, generators only run once someone calls for the &lt;code&gt;next&lt;/code&gt; value.&lt;/p&gt;
&lt;p&gt;It&apos;s possible to go through a generator using a simple for-of-loop.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for (const num of range(1, 10)) {
  console.log(num);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using the Iterable interface&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const iterator = range(1, 10)[Symbol.iterator]();
while (true) {
  const { done, value } = iterator.next();
  if (done) break;
  console.log(value);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or using the spread operator to save all the values in an Array.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for (const num of [...range(1, 10)]) {
  console.log(num);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&apos;s important to remember that if you use the spread operator, you will lose all the generators&apos; benefits because it runs the generator until it&apos;s not completed to copy all the values in the array.&lt;/p&gt;
&lt;p&gt;Like iterators also, generators can be combined. For instance, we can create a map generator function that accepts an iterator and a transformation function and returns the computation inside the transformation with the value emitted by the generator.&lt;/p&gt;
&lt;p&gt;And that&apos;s the result.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function* map&amp;lt;T, U&amp;gt;(
  iterable: Iterable&amp;lt;T&amp;gt;,
  callback: (value: T) =&amp;gt; U
): Iterable&amp;lt;U&amp;gt; {
  for (const value of iterable) {
    yield callback(value);
  }
}

const mapRange = map(range(1, 10), value =&amp;gt; value * 10);

for (const num of mapRange) {
  console.log(num);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&apos;s all folks. You can find a video about them on my &lt;a href=&quot;https://www.youtube.com/@Puppo_92/&quot;&gt;Youtube channel&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://youtu.be/mi2JlrXBRIs&quot;&gt;https://youtu.be/mi2JlrXBRIs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In conclusion, JavaScript generators stand as a remarkable tool in the arsenal of every developer striving for more efficient and flexible programming. Through their unique ability to pause and resume execution, generators provide an innovative solution to managing complex flows of data and operations.&lt;/p&gt;
&lt;p&gt;Throughout this blog post, we&apos;ve journeyed through the syntax, use cases, and benefits of JavaScript generators. We&apos;ve seen how they can simplify code, making it more readable and maintainable.&lt;/p&gt;
&lt;p&gt;By harnessing the power of generators, you can transform the way you approach programming challenges. These constructs not only offer a structured approach to handling tasks but also contribute to writing code that is less error-prone and easier to reason about.&lt;/p&gt;
&lt;p&gt;As you venture into the realm of generators, remember that practice is key. Experiment with different scenarios, explore their interplay with other techniques and gradually integrate them into your projects. With time, you&apos;ll become proficient in leveraging generators to create responsive and efficient applications.&lt;/p&gt;
&lt;p&gt;So, whether you&apos;re a front-end developer aiming to tame complex UI interactions or a back-end engineer dealing with intricate data processing, generators offer a fresh perspective on tackling programming. Embrace their power, refine your skills, and elevate your coding prowess in the dynamic world of JavaScript.&lt;/p&gt;
&lt;p&gt;Thank you for reading and happy generating! 👩💻 👨💻 😜&lt;/p&gt;
&lt;p&gt;N.B. you can find the code of this post &lt;a href=&quot;https://github.com/Puppo/javascript-iterators-and-generators/tree/02-generators&quot;&gt;in the GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>generators</category><category>generator</category><category>js</category></item><item><title>Iterate Like a Pro: Mastering JavaScript Iterators for Effortless Code</title><link>https://delpuppo.net/blog/js-iterators-generators/iterate-like-a-pro-mastering-javascript-iterators-for-effortless-code/</link><guid isPermaLink="true">https://delpuppo.net/blog/js-iterators-generators/iterate-like-a-pro-mastering-javascript-iterators-for-effortless-code/</guid><description>Welcome to this blog post, where we&apos;re about to unravel the power and versatility of JavaScript...</description><pubDate>Fri, 25 Aug 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome to this blog post, where we&apos;re about to unravel the power and versatility of JavaScript iterators. If you&apos;ve ever found yourself working with data collections and wondered if there&apos;s a more efficient and elegant way to navigate them, you&apos;re in the right place.&lt;/p&gt;
&lt;p&gt;In the realm of modern web development, efficiently managing and manipulating data is a crucial skill. This is where JavaScript iterators come into play, offering a systematic approach to traversing various data structures such as arrays, maps, and sets. Whether you&apos;re a beginner eager to understand the basics or an experienced developer looking to fine-tune your code, grasping the concept of iterators can significantly enhance your programming journey.&lt;/p&gt;
&lt;p&gt;In this blog post, we&apos;ll embark on a comprehensive exploration of JavaScript iterators. We&apos;ll break down their fundamental principles, explore practical examples of their usage, and demonstrate how they can simplify complex data operations. By the time you finish reading, you&apos;ll not only understand iterators inside and out but also be equipped to leverage their potential to write more concise, readable, and efficient code.&lt;/p&gt;
&lt;p&gt;So, whether you&apos;re striving to make your codebase more elegant or seeking to optimize your data manipulation techniques, join us as we delve into the world of JavaScript iterators. From novice to expert, there&apos;s something here for everyone. Let&apos;s dive in!&lt;/p&gt;
&lt;p&gt;Built-in in Javascript exists many structures that implement the Iterators pattern, for instance: Array, Set and Map. In Javascript, an object to be iterable must implement the Iterable interface.&lt;/p&gt;
&lt;p&gt;But what is the Iterable interface? First, to be iterable, an object must have a &lt;code&gt;next&lt;/code&gt; method. This method must return two properties: &lt;code&gt;done&lt;/code&gt; and &lt;code&gt;value&lt;/code&gt;. Done is used to detect if the iteration is completed; instead, the value contains the current value. Last but not least, if you want your object to become an iterator, you must expose the iterable interface in the &lt;code&gt;Symbol.iterator&lt;/code&gt; of your object, like in this example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const array = [1, 2, 3, 4, 5];
const iterator = array[Symbol.iterator]();
for (let result = iterator.next(); !result.done; result = iterator.next()) {
  console.log(result.value);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, here is a range function implemented as an iterator.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const range = (start: number, end: number): Iterable&amp;lt;number&amp;gt; =&amp;gt; {
  return {
    [Symbol.iterator]() {
      let n = start;
      return {
        next() {
          console.log(&quot;range next&quot;);
          if (n &amp;gt; end) {
            return { done: true, value: null };
          }
          return { done: false, value: n++ };
        },
      };
    },
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, this function accepts two numbers, start and end and returns a new object with a single property, in this case, the iterator property. Then, inside this function, there is the next function that, on every call, checks if the current value is greater than the end and, if true, returns a new object with done as true and value as null; else returns an object with done false and value with the current value. The beautiful thing about iterator is that javascript only does something once you ask for the next value.&lt;/p&gt;
&lt;p&gt;Every iterator can be iterated using the for-of loop&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for (const num of range(1, 10)) {
  console.log(num);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or using its native method, so calling the &lt;code&gt;Symbol.iterator&lt;/code&gt; function and then using the next method and checking the done property if it is true or not.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const rangeIterator = range(1, 10)[Symbol.iterator]();
for (let result = rangeIterator.next(); !result.done; result = rangeIterator.next()) {
  console.log(result.value);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&apos;s possible to copy all the iterator values in an Array using the spread operator too.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for (const num of [...range(1, 10)]) {
  console.log(num);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Iterator also has another method, the &lt;code&gt;return&lt;/code&gt; method. This method is used in case the code doesn&apos;t complete the iteration. Imagine the loop call a break or a return; in this case, JavaScript under the hood calls the &lt;code&gt;return&lt;/code&gt; method for us. In this method, we can handle whatever we need. We may need to reset something or check the current value of the iterator.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const range = (start: number, end: number): Iterable&amp;lt;number&amp;gt; =&amp;gt; {
  return {
    [Symbol.iterator]() {
      let n = start;
      return {
        next() {
          console.log(&quot;range next&quot;);
          if (n &amp;gt; end) {
            return { done: true, value: null };
          }
          return { done: false, value: n++ };
        },
        return() {
          console.log(&quot;range return&quot;);
          return { done: true, value: null };
        },
      };
    },
  };
};

for (const num of range(1, 10)) {
  if (num &amp;gt; 5) break;
  console.log(num);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Iterators are powerful, and we can also create functions that accept an iterator and manipulate it to return another iterator. For instance, we can create a map function that accepts an iterator and returns another with a callback specified by the user.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function mapIterable&amp;lt;T, U&amp;gt;(
  iterable: Iterable&amp;lt;T&amp;gt;,
  callback: (value: T) =&amp;gt; U
): Iterable&amp;lt;U&amp;gt; {
  return {
    [Symbol.iterator]() {
      const iterator = iterable[Symbol.iterator]();
      return {
        next() {
          console.log(&quot;mapIterable next&quot;);
          const { done, value } = iterator.next();
          if (done) {
            return { done: true, value: null };
          }
          return { done, value: callback(value) };
        },
        return() {
          console.log(&quot;mapIterable return&quot;);
          if (iterator.return) {
            iterator.return();
          }
          return { done: true, value: null };
        },
      };
    },
  };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All the info said before is true also for this new iterator. JavaScript does nothing until the codebase doesn&apos;t ask for the next value; the same is true for the return method, and now you can compose the range iterators with the map iterator to build a new one.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const mapRange = mapIterable(range(1, 10), value =&amp;gt; value * 10);

for (const num of mapRange) {
  if (num &amp;gt; 50) break;
  console.log(num);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok folks, that&apos;s all!&lt;br /&gt;
If you want to dive deep with Iterators, don&apos;t waste my video on my &lt;a href=&quot;https://www.youtube.com/@Puppo_92/&quot;&gt;Youtube Channel&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=BSctSkMGtiM&quot;&gt;https://www.youtube.com/watch?v=BSctSkMGtiM&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In conclusion, understanding and utilizing JavaScript iterators can greatly enhance your ability to work with collections of data in a more elegant and efficient manner. With iterators, you can streamline your code, improve its readability, and reduce memory consumption by processing data one element at a time. This powerful concept empowers developers to implement custom iteration behaviour, making their code more adaptable to different scenarios.&lt;/p&gt;
&lt;p&gt;By grasping the fundamentals of iterators, such as the &lt;code&gt;next()&lt;/code&gt; method and the concept of iterable objects, you open the door to more sophisticated programming techniques and design patterns. Whether you&apos;re working with arrays, maps, sets, or other data structures, iterators provide a standardized way to traverse through data and perform operations without unnecessary complexity.&lt;/p&gt;
&lt;p&gt;As the JavaScript language continues to evolve, iterators remain a foundational concept that plays a crucial role in modern programming paradigms. Incorporating iterators into your coding arsenal equips you with a versatile tool for managing data, ultimately leading to cleaner, more maintainable, and more robust code.&lt;/p&gt;
&lt;p&gt;So, as you embark on your journey to master JavaScript iterators, remember that they are more than just technical features; they represent a shift in how you approach and solve problems in your code. With practice and exploration, you&apos;ll be able to wield iterators effectively, making your codebase more efficient and your development experience more enjoyable.&lt;/p&gt;
&lt;p&gt;Thanks for reading and Happy coding! 😃 👩💻 👨💻&lt;/p&gt;
&lt;p&gt;N.B. you can find the code of this article &lt;a href=&quot;https://github.com/Puppo/javascript-iterators-and-generators/tree/01-iterators&quot;&gt;in the GitHub repository&lt;/a&gt;!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>javascript</category><category>iterators</category><category>iterator</category><category>js</category></item><item><title>🏆 My journey to the MVP Award 🏆</title><link>https://delpuppo.net/blog/my-journey-to-the-mvp-award/</link><guid isPermaLink="true">https://delpuppo.net/blog/my-journey-to-the-mvp-award/</guid><description>This history started many years ago! I was a student, and I was going to the ITS in Pordenone. I...</description><pubDate>Fri, 09 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This history started many years ago! I was a student, and I was going to the &lt;a href=&quot;https://www.itsaltoadriatico.it/&quot;&gt;ITS&lt;/a&gt; in Pordenone.&lt;br /&gt;
I spent two years of my life in that school, where I met great friends and learned a lot from awesome teachers, one of them is &lt;a href=&quot;https://www.dottor.net/&quot;&gt;Andrea Dottor&lt;/a&gt;.&lt;br /&gt;
In the first lesson with him, he started with his presentation, &quot;I&apos;m a freelancer, I work with different companies and blah blah blah... I&apos;m a Microsoft MVP too&quot;.&lt;br /&gt;
That was the first time that I heard about this program. As you can imagine, I was 20, and I didn&apos;t get any importance to that tense, but in reality, it was the first moment that I came across the MVP program.&lt;/p&gt;
&lt;p&gt;After that, Andrea and I became colleagues and friends. I always see Andrea as a Mentor, and I have always followed him. So I started to go with him to the &lt;a href=&quot;https://www.xedotnet.org/&quot;&gt;xedotnet&lt;/a&gt; meetup. I met other incredible developers like &lt;a href=&quot;https://mvp.microsoft.com/en-us/PublicProfile/4039714?fullName=Mirco%20Vanini&quot;&gt;Mirco Vanini&lt;/a&gt; (another MVP), Daniele Morosinotto and many others there. Thanks to xe, I learned what a community is and how a community works. I started to understand the benefit of sharing knowledge in the development environment, and my mind started to build a strange idea &quot;One day you will be like them, maybe not an MVP but a speaker yes, and you will share your knowledge with the others.&quot;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I was young at that moment and decided to continue to follow the community, but I put my effort into improving myself in my job.&lt;br /&gt;
For almost 8 years, I dedicated my time to learn stuff in my bedroom and in my free time, developing different projects in my daily routine, and I changed 3 jobs too.&lt;br /&gt;
When I started to work in Flowing, in my mind something happened.&lt;br /&gt;
Flowing was an environment with awesome developers, and many of them were and are speakers too. But I was not ready to do my first talk, so I tried to think of something different that could be useful for the community. After some days, I decided to write my first series about Typescripts.&lt;br /&gt;
Why typescript? It is my favorite language with javascript, and many times, I saw people fighting with it. So I said: &quot;Ok, this is the right topic, let&apos;s go!&quot;.&lt;br /&gt;
21 articles compose my first series, &quot; &lt;strong&gt;Typescript - Tips &amp;amp; Tricks Series&lt;/strong&gt;&quot;, which you can find &lt;a href=&quot;https://dev.to/puppo/series/11213&quot;&gt;in this reference&lt;/a&gt;. In reality, the audience at the beginning was not so much, but after some months, &lt;a href=&quot;https://twitter.com/LayZeeDK&quot;&gt;Lars&lt;/a&gt; contacted me to ask if I would join the &quot;&lt;a href=&quot;https://dev.to/this-is-learning&quot;&gt;This is learning&lt;/a&gt;&quot; community, and as you can imagine, I accepted :) Here I also met another good man: &lt;a href=&quot;https://twitter.com/SantoshYadavDev&quot;&gt;Santosh&lt;/a&gt;, who runs with Lars &quot;This is learning&quot; community.&lt;br /&gt;
During that period, another crazy and good friend had a strange idea. I organized and took as &quot;Teacher&quot; a workshop about Nx in Flowing, and he was invited as an attendee. He appreciated the workshop so much that he invited me to his youtube channel to speak about Nx (&lt;a href=&quot;https://www.youtube.com/watch?v=hS_2Okd-CkM&quot;&gt;Nx the return&lt;/a&gt;). The name of the friend is &lt;a href=&quot;https://mvp.microsoft.com/en-us/PublicProfile/5003974?fullName=Francesco%20Sciuti&quot;&gt;Francesco Sciuti&lt;/a&gt;, another MVP and also the Batman of the developers.&lt;br /&gt;
In that period, I was also writing a new series called &quot;&lt;a href=&quot;https://dev.to/puppo/series/13743&quot;&gt;RxJS - Getting Started&lt;/a&gt;&quot;, 15 articles to help developers to be more confident with &lt;a href=&quot;https://rxjs.dev/&quot;&gt;RxJS&lt;/a&gt;. Why this topic? Because I worked on many Angular projects and saw many developers stuck or completely unfamiliar with it.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;After that, a colleague and friend (&lt;a href=&quot;https://www.linkedin.com/in/francescostrazzullo/&quot;&gt;Francesco Strazzullo&lt;/a&gt;) tried to push me out of my comfort zone, and he asked me to be a speaker at the &lt;a href=&quot;https://marcausergroup.it/&quot;&gt;Mug&lt;/a&gt; meetup. I was a bit scared; speaking in front of many people created a strange sensation in me, but after some sane pushing, I said yes! So the 7th of October 2021, I did my first talk called &lt;a href=&quot;https://marcausergroup.it/eventi/2021/10/07/stay-reactive-stay-quiet-with-rxjs.html&quot;&gt;Stay Reactive Stay Quiet with RxJS&lt;/a&gt;. The sensations at the end were really good, so on the 19th of October, I did the second at the &lt;a href=&quot;https://www.fevr.it/&quot;&gt;FEVR&lt;/a&gt; community called &quot;&lt;a href=&quot;https://www.fevr.it/eventi/2021/10/is-it-possible-to-build-your-ui-components-using-only-web-components/&quot;&gt;Is it possible to build your UI components using only web components?&lt;/a&gt;&quot; (thanks to &lt;a href=&quot;https://www.linkedin.com/in/matteoguidotto/&quot;&gt;Matteo Guidotto&lt;/a&gt; for this talk).&lt;br /&gt;
It was the COVID period, so taking talks and doing conferences in 2021 was really difficult. For this reason, I continued to write another series called: &lt;a href=&quot;https://dev.to/puppo/series/15827&quot;&gt;It&apos;s Prisma Time&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At the beginning of 2022, the decisive turning point. During a chat with Andrea, I told him: &quot;I would become a Microsoft MVP; what have I to do to achieve it?&quot; I had this idea for some months, but I wanted to concretize it at that moment. He looked at me and said, &quot;It&apos;s time to do some great conferences and maybe speak more about some Microsoft technologies&quot;.&lt;br /&gt;
So I went back home, and with the euphoria in my blood, I started to write some articles about &lt;a href=&quot;https://dev.to/puppo/series/16773&quot;&gt;Visual Studio Code&lt;/a&gt;. These articles spoke about some common commands for me when I worked with VsCode, but these articles were awesome for the community! Many and many people didn&apos;t know these commands, and the articles received a lot of appreciation. Another thing I did was research conferences and check out conferences where I could send a CFP.&lt;br /&gt;
I remember I sent so many CFPs that I forgot how many noes I received 😅&lt;br /&gt;
But at the beginning of September, the first confirmations arrived: &lt;a href=&quot;https://2022.angularday.it/talks_speakers/&quot;&gt;AngularDay 2022&lt;/a&gt;, then the &lt;a href=&quot;https://2022.reactjsday.it/workshop/workshop_Unit-Test.html&quot;&gt;workshop&lt;/a&gt; at the react day with &lt;a href=&quot;https://mvp.microsoft.com/en-us/PublicProfile/5003526?fullName=Fabio%20Biondi&quot;&gt;Fabio Biondi&lt;/a&gt;, another MVP and good friend that shared with me also a great weekend at the GDP Pescara, where I talked about &lt;a href=&quot;https://devfest.gdgpescara.it/sessions/304&quot;&gt;Prisma&lt;/a&gt; and last but not least the &lt;a href=&quot;https://www.youtube.com/watch?v=h_Faplx37yk&quot;&gt;ngrome&lt;/a&gt;.&lt;br /&gt;
During this period, I also continued to do meetups, thanks to &lt;a href=&quot;https://www.meetup.com/it-IT/milano-front-end/&quot;&gt;Milano Frontend&lt;/a&gt; and &lt;a href=&quot;https://www.meetup.com/it-IT/react-js-milano/&quot;&gt;React JS Milano&lt;/a&gt; having me as a speaker.&lt;br /&gt;
If you are curious, you can find the list of all my talks and contributions &lt;a href=&quot;https://mvp.microsoft.com/en-us/PublicProfile/5005133?fullName=Luca%20Del%20Puppo&quot;&gt;in this reference&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In the middle of December 2022, I spoke again with Andrea to ask him if he could nominate me as Microsoft MVP. He did it, and I spent an evening filling out the form of all my contributions during the last year. Why last year? Because the MVP Award is based on the last year. I started my history 10 years ago, yes, but the MVP Award takes into consideration only the last year. I decided to tell you the entire story because I know the last year is only the cherry on top, but without the previous nine, the last year would probably be a failure.&lt;/p&gt;
&lt;p&gt;As you can imagine, after the filling, you have to wait for the evaluation, which takes at most 3 months. I was lucky; on the 3rd of January 2023, in my inbox appeared an email that said: &quot;Congratulation! You are a Microsoft MVP 2023&quot;! Now, I suppose you can imagine how much happy I was, I think I stayed euphory for the following two or three days 😅&lt;br /&gt;
Then after some weeks, I did a call with &lt;a href=&quot;https://www.linkedin.com/in/crisgonz/&quot;&gt;Cristina&lt;/a&gt;. She takes care of all the MVPs on the Meditterian side and explained to me how the program works, its benefits and so on. She is really kind and she really put a lot of effort into helping the MVPs. Thanks Cristina, for all the things you do for us! 🫶&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Now my journey is only at the beginning. I have different ideas for continuing.&lt;br /&gt;
I opened my own &lt;a href=&quot;https://www.youtube.com/@Puppo_92&quot;&gt;Youtube channel,&lt;/a&gt; I&apos;ll continue to write articles, and I&apos;ll continue to do talks at conferences and meetups.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What did I learn from this story?&lt;/strong&gt;&lt;br /&gt;
The MVP award is &quot;only&quot; a simple and beautiful award that helps me remember all the effort I put in these years to improve myself and try to help others! And if you want to join the program: love communities, and put your effort into helping them! Do this, and you&apos;ll be on the right path to being part of the MVP Family.&lt;br /&gt;
Remember: &lt;strong&gt;improve yourself, help others and follow your passion!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@vladbagacian?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Vlad Bagacian&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>mvp</category><category>award</category><category>microsoft</category><category>journey</category><category>Awards</category></item><item><title>React Query - Infinite Queries</title><link>https://delpuppo.net/blog/react-query/react-query-infinite-queries/</link><guid isPermaLink="true">https://delpuppo.net/blog/react-query/react-query-infinite-queries/</guid><description>Hey Folks, Today it&apos;s time to learn how you can build an infinite query with React Query. To build...</description><pubDate>Wed, 07 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey Folks,&lt;/p&gt;
&lt;p&gt;Today it&apos;s time to learn how you can build an infinite query with React Query.&lt;/p&gt;
&lt;p&gt;To build an infinite query you have to use the &lt;code&gt;useInfiniteQuery&lt;/code&gt; hook. This hook is similar to the &lt;code&gt;useQuery&lt;/code&gt; but with some more properties to handle the infinite loading in the best way.&lt;/p&gt;
&lt;p&gt;The key concepts, if you are working with &lt;code&gt;useInfiniteQuery&lt;/code&gt; are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Key&lt;/strong&gt; : in this case, the key is unique for each page, &lt;code&gt;useInfiniteQuery&lt;/code&gt; handles all the pages inside its state&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;page&lt;/strong&gt; : each chunk of your infinite query is represented as a page and the first page returned by the &lt;code&gt;useInfiniteQuery&lt;/code&gt; is undefined. This helps you to understand if it&apos;s the first iteration or not.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;hasNextPage&lt;/strong&gt; : is a variable returned by the hook and its scope is to determine if another chunk exists or not&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;fetchNextPage&lt;/strong&gt; : is a function used to fetch the next chunk&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;isLoading&lt;/strong&gt; : is a flag that determines if there is a loading ongoing (The query has no data yet)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;isFetching&lt;/strong&gt; : is a flag that determines if there is a fetch request ongoing&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;getNextPageParam&lt;/strong&gt; : this function is an option to pass at the hook and it is used to determine if there is another chunk or not after the response&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ok, let&apos;s see the code to be clearer&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { useInfiniteQuery } from &apos;@tanstack/react-query&apos;;
import { useState } from &apos;react&apos;;

const fetchTodos = async (
  page: number,
  limit: number,
  signal: AbortSignal | undefined
): Promise&amp;lt;{
  totals: number;
  todos: Todo[];
}&amp;gt; =&amp;gt; {
  const response = await fetch(`api/tasks?_page=${page + 1}&amp;amp;_limit=${limit}`, {
    signal,
  });
  if (!response.ok) {
    throw new ResponseError(&apos;Failed to fetch todos&apos;, response);
  }
  const todos: Todo[] = await response.json();
  const totals = Number.parseInt(
    response.headers.get(&apos;x-total-count&apos;) || &apos;0&apos;,
    10
  );

  return {
    totals,
    todos,
  };
};

interface UseTodos {
  todos: Todo[];
  isLoading: boolean;
  isFetching: boolean;
  error?: string;
  hasNext: boolean;
  next?: () =&amp;gt; void;
}

export const useTodos = (): UseTodos =&amp;gt; {
  const [limit] = useState&amp;lt;number&amp;gt;(5);

  const { data, hasNextPage, fetchNextPage, isLoading, isFetching, error } =
    useInfiniteQuery(
      [QUERY_KEY.todos],
      ({ signal, pageParam: page = 0 }) =&amp;gt; fetchTodos(page, limit, signal),
      {
        refetchOnWindowFocus: false,
        retry: 2,
        getNextPageParam: (lastPage, pages) =&amp;gt; {
          if (Math.ceil(lastPage.totals / limit) &amp;gt; pages.length)
            return pages.length;
          return undefined;
        },
      }
    );

  return {
    todos: data?.pages.flatMap(({ todos }) =&amp;gt; todos) || [],
    isLoading,
    isFetching,
    error: mapError(error),
    next: fetchNextPage,
    hasNext: hasNextPage || false,
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, the flow is very simple, the hook returns the current page or chunk, you have to handle the fetch request and then you can determine the result and if there is another chunk or not.&lt;br /&gt;
Another important thing to keep in mind is that the result of the &lt;code&gt;useInfiniteQuery&lt;/code&gt; is an array and each element of the array contains the data of each chunk.&lt;/p&gt;
&lt;p&gt;Ok, I suppose you have an idea of how Infinite Queries work in React Query, but if you want to deep into it don&apos;t miss my youtube about it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=F1KD4GY1iws&quot;&gt;https://www.youtube.com/watch?v=F1KD4GY1iws&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think thats all from this article.&lt;/p&gt;
&lt;p&gt;This is the last post of this series, I hope you enjoyed the content and now you are aware of using ReactQuery in your React application.&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;br /&gt;
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the code of the video &lt;a href=&quot;https://github.com/Puppo/learning-react-query/tree/12-infinitive-scroll&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rahuulmiishra?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Rahul Mishra&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>react</category><category>reactquery</category><category>reacthooks</category></item><item><title>React Query - Paginated List</title><link>https://delpuppo.net/blog/react-query/react-query-paginated-list/</link><guid isPermaLink="true">https://delpuppo.net/blog/react-query/react-query-paginated-list/</guid><description>Hey Folks, Today it&apos;s time to learn how you can paginate a list with ReactQuery. It&apos;s common to...</description><pubDate>Thu, 01 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey Folks,&lt;/p&gt;
&lt;p&gt;Today it&apos;s time to learn how you can paginate a list with ReactQuery.&lt;/p&gt;
&lt;p&gt;It&apos;s common to create a pagination of a list to improve the user interface of your platform if you are building a list in your application, but also to limitate the work in your API.&lt;/p&gt;
&lt;p&gt;Using ReactQuery, building a paginate list is a piece of cake.&lt;/p&gt;
&lt;p&gt;You have to follow 3 steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Create a state to save the value of the current page&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a state to save the limit of the pages (the number of elements on every page)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fetch the data every time the user changes one of the previous states.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But let&apos;s see an example that is easier to understand&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const fetchTodos = async (
  page: number,
  limit: number,
  signal: AbortSignal | undefined
): Promise&amp;lt;{
  totals: number;
  todos: Todo[];
}&amp;gt; =&amp;gt; {
  const response = await fetch(`api/tasks?_page=${page}&amp;amp;_limit=${limit}`, {
    signal,
  });
  if (!response.ok) {
    throw new ResponseError(&apos;Failed to fetch todos&apos;, response);
  }
  const todos: Todo[] = await response.json();
  const totals = Number.parseInt(
    response.headers.get(&apos;x-total-count&apos;) || &apos;0&apos;,
    10
  );

  return {
    totals,
    todos,
  };
};

interface UseTodos {
  todos: Todo[];
  isLoading: boolean;
  isFetching: boolean;
  error?: string;
  pages: number;
  page: number;
  setPage: Dispatch&amp;lt;SetStateAction&amp;lt;number&amp;gt;&amp;gt;;
}

export const useTodos = (): UseTodos =&amp;gt; {
  const [page, setPage] = useState&amp;lt;number&amp;gt;(1);
  const [limit] = useState&amp;lt;number&amp;gt;(5);

  const {
    data: { todos, totals } = {
      todos: [],
      totals: 0,
    },
    isLoading,
    isFetching,
    error,
  } = useQuery(
    [QUERY_KEY.todos, page, limit],
    ({ signal }) =&amp;gt; fetchTodos(page, limit, signal),
    {
      refetchOnWindowFocus: false,
      retry: 2,
    }
  );

  return {
    todos,
    isLoading,
    isFetching,
    error: mapError(error),
    pages: Math.ceil(totals / limit),
    page,
    setPage,
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, the process to build a pagination with ReactQuery is very simple.&lt;br /&gt;
The fetch request has to contain the page and the limit (you can handle a pagination also with limit and offset if you want) and in your &lt;code&gt;useQuery&lt;/code&gt; you have to handle some simple stuff. First, the key of your query must include the page and limit too, second you must pass page and limit to your fetch request.&lt;/p&gt;
&lt;p&gt;As you can see, building a paginated list with ReactQuery is really a piece of cake, but if want to dive into it don&apos;t miss my youtube video about it&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=Ma7-hdNMdWs&quot;&gt;https://www.youtube.com/watch?v=Ma7-hdNMdWs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think thats all from this article; I hope you enjoyed this content!&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;br /&gt;
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the code of the video &lt;a href=&quot;https://github.com/Puppo/learning-react-query/tree/11-paginate-result&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rahuulmiishra?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Rahul Mishra&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>react</category><category>reactquery</category><category>reacthooks</category></item><item><title>React Query - Abort Request</title><link>https://delpuppo.net/blog/react-query/react-query-abort-request/</link><guid isPermaLink="true">https://delpuppo.net/blog/react-query/react-query-abort-request/</guid><description>Hey Folks, Today it&apos;s time to learn how you can abort an ongoing request with ReactQuery. Before...</description><pubDate>Wed, 17 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey Folks,&lt;/p&gt;
&lt;p&gt;Today it&apos;s time to learn how you can abort an ongoing request with ReactQuery.&lt;/p&gt;
&lt;p&gt;Before moving to the example, I want to introduce the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal&quot;&gt;AbortSignal&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;AbortSignal is a javascript interface used to abort ongoing methods. Typically, you can create an AbortSignal by an &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/AbortController&quot;&gt;AbortController&lt;/a&gt;, which simplifies the creation and execution of the AbortSignal. When you create an AbortController (&lt;code&gt;controller = new AbortController()&lt;/code&gt;) you get an instance of it that has two core concepts: the signal (&lt;code&gt;controller.signal&lt;/code&gt;) and the abort method (&lt;code&gt;controller.abort()&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The first one is important because it contains the signal with its status, and the second one is important because it allows you to change the status of the abort from &lt;code&gt;false&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Using these two interfaces, in javascript, you can handle out-of-the-box the abort of an HTTP request created with the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API&quot;&gt;fetch API&lt;/a&gt; but also with &lt;a href=&quot;https://axios-http.com&quot;&gt;axios&lt;/a&gt; if you want. When you create a request, both accept a signal and if you abort that signal you can abort the request.&lt;/p&gt;
&lt;p&gt;AbortSignal has also a static method called &lt;code&gt;timeout&lt;/code&gt; that accepts a number that describes the timeout time in milliseconds. Using this method you can create easily a signal that changes its status after some time. Very common if you want to handle a timeout of your request.&lt;/p&gt;
&lt;p&gt;Just a quick example to make you understand the power of these interfaces.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;try {
  const controller = new AbortController();
  const timeoutId = setTimeout(() =&amp;gt; controller.abort(), 5000);
  const res = await fetch(url, { signal: controller.signal });
  const body = await res.json();
} catch (e) {
  if (e.name === &quot;AbortError&quot;) {
    // Notify the user of abort.
    // Note this will never be a timeout error!
  } else {
    // A network error, or some other problem.
    console.log(`Type: ${e.name}, Message: ${e.message}`);
  }
} finally {
  clearTimeout(timeoutId);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, you can see an abort request created with an AbortController. This example uses a setTimeout method to handle the timeout and as you can notice, when the code creates the fetch API passes the signal status to the fetch. In this way, the fetch request and the signal are linked together. This example could be simplified in this way using the AbortSignal timeout method.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;try {
  const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
  const body = await res.json();
} catch (e) {
  if (e.name === &quot;AbortError&quot;) {
    // Notify the user of abort.
    // Note this will never be a timeout error!
  } else {
    // A network error, or some other problem.
    console.log(`Type: ${e.name}, Message: ${e.message}`);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok, now you have an idea of how AbortSignal and AbortController work, so we can move on to the next step; how can you abort a request with ReactQuer?&lt;/p&gt;
&lt;p&gt;Good news for you, ReactQuery out-of-the-box handles a signal for you for every query and mutation, and your business it&apos;s only decided if you want to use it or not.&lt;/p&gt;
&lt;p&gt;Let&apos;s start with an example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const fetchTodos = async (signal: AbortSignal | undefined): Promise&amp;lt;Todo[]&amp;gt; =&amp;gt; {
  const response = await fetch(&apos;api/tasks&apos;, {
    signal,
  });
  if (!response.ok) {
    throw new ResponseError(&apos;Failed to fetch todos&apos;, response);
  }
  return await response.json();
};

interface UseTodos {
  todos: Todo[];
  isLoading: boolean;
  isFetching: boolean;
  error?: string;
  setUserFilter: Dispatch&amp;lt;SetStateAction&amp;lt;number | null&amp;gt;&amp;gt;;
}

export const useTodos = (): UseTodos =&amp;gt; {
  const client = useQueryClient();

  const {
    data: todos = [],
    isLoading,
    isFetching,
    error,
  } = useQuery([QUERY_KEY.todos], ({ signal }) =&amp;gt; fetchTodos(signal), {
    refetchOnWindowFocus: false,
    retry: 2
  });

  return {
    todos,
    isLoading,
    isFetching,
    error: mapError(error),
    setUserFilter,
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, &lt;code&gt;useQuery&lt;/code&gt; has a second parameter that contains different options, one of them is the signal. This signal is an AbortSignal that you can use to abort your request if you want. In the example, for instance, the signal is passed to the &lt;code&gt;fetchTodos&lt;/code&gt; method and then passed to fetch request.&lt;/p&gt;
&lt;p&gt;As you can understand, aborting a request is a piece of cake 🍰&lt;/p&gt;
&lt;p&gt;Ok, I think now you have all the notions to abort an HTTP request in javascript and in ReactQuery too.&lt;/p&gt;
&lt;p&gt;If you want to go dive into the Abort Request with React query don&apos;t miss my Youtube channel 🚀&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=BL_E7SrymWI&quot;&gt;https://www.youtube.com/watch?v=BL_E7SrymWI&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think thats all from this article; I hope you enjoyed this content!&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;br /&gt;
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the code of the video &lt;a href=&quot;https://github.com/Puppo/learning-react-query/tree/10-abort-request&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rahuulmiishra?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Rahul Mishra&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>react</category><category>reactquery</category><category>reacthooks</category></item><item><title>Improve user experience with optimistic update</title><link>https://delpuppo.net/blog/react-query/improve-user-experience-with-optimistic-update/</link><guid isPermaLink="true">https://delpuppo.net/blog/react-query/improve-user-experience-with-optimistic-update/</guid><description>Hey Folks, Sometimes to improve the user experience you can decide to bet on the success of your...</description><pubDate>Thu, 11 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey Folks,&lt;/p&gt;
&lt;p&gt;Sometimes to improve the user experience you can decide to bet on the success of your code, so you can assume that the code will go in the right way to make your application faster in the eyes of your users. This approach is called Optimistic Update and can be handled in some lines of code using react query with the &lt;code&gt;useMutation&lt;/code&gt; hook. Yes, this approach is like a bet with the code but it&apos;s also important to keep in mind to handle the errors in case of failure.&lt;/p&gt;
&lt;p&gt;To handle the optimistic update you have to handle an &lt;code&gt;useMutation&lt;/code&gt; hook in your codebase. This hook exposes three events to handle to perform the optimistic update: &lt;code&gt;onMutate&lt;/code&gt;, &lt;code&gt;onSuccess&lt;/code&gt; and the &lt;code&gt;onError&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;onMutate&lt;/code&gt; event is called immediately when your code calls the &lt;code&gt;useMutation&lt;/code&gt; hook. This event is used to create a snapshot of the current state before moving forward and updating the state with the new values. It&apos;s important to save the previous state because it permits you in case of failure to restore it in the future if needed.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;onSuccess&lt;/code&gt; event is called in case of success of the mutation. If your code jumps in this event, you are safe and everything has gone in the right way.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;onError&lt;/code&gt; event is called in case of failure of the mutation. If your code is inside of this event unfortunately something went wrong. In this case, you must handle the restoration of the state to the previous one and notify the user that something went wrong.&lt;/p&gt;
&lt;p&gt;To help you to understand better the case let&apos;s see an example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { useMutation, useQueryClient } from &apos;@tanstack/react-query&apos;;
import { useSnackbar } from &apos;notistack&apos;;

const editTodoRequest = async (todo: Todo): Promise&amp;lt;Todo&amp;gt; =&amp;gt; {
  await new Promise((resolve) =&amp;gt; setTimeout(resolve, 3000));
  const response = await fetch(`api/tasks/${todo.id}`, {
    method: &apos;PUT&apos;,
    headers: {
      &apos;Content-Type&apos;: &apos;application/json&apos;,
    },
    body: JSON.stringify(todo),
  });
  if (!response.ok) {
    throw new ResponseError(`Failed to edit todo with id ${todo.id}`, response);
  }
  return await response.json();
};

type UseEditTodo = (todo: Todo) =&amp;gt; void;

export const useEditTodo = (): UseEditTodo =&amp;gt; {
  const { enqueueSnackbar, closeSnackbar } = useSnackbar();
  const client = useQueryClient();
  const { mutate: editTodo } = useMutation&amp;lt;
    Todo,
    unknown,
    Todo,
    {
      oldTodos?: Todo[];
      oldTodo?: Todo;
      messageKey: string | number;
    }
  &amp;gt;(editTodoRequest, {
    onMutate: (todo) =&amp;gt; {
      const messageKey = enqueueSnackbar(&apos;Todo edited&apos;, {
        variant: &apos;success&apos;,
      });
      const oldTodos = client.getQueryData&amp;lt;Todo[]&amp;gt;([QUERY_KEY.todos]);
      const oldTodo = client.getQueryData&amp;lt;Todo&amp;gt;([QUERY_KEY.todos, todo.id]);
      client.setQueryData([QUERY_KEY.todos, todo.id], todo);
      client.setQueryData&amp;lt;Todo[]&amp;gt;([QUERY_KEY.todos], (oldTodos) =&amp;gt;
        oldTodos?.map((oldTodo) =&amp;gt; (oldTodo.id === todo.id ? todo : oldTodo))
      );

      return {
        oldTodos,
        oldTodo,
        messageKey,
      };
    },
    onSuccess: () =&amp;gt; {
      client.invalidateQueries([QUERY_KEY.todos]);
    },
    onError: (error, todo, ctx) =&amp;gt; {
      if (!ctx) return;
      const { oldTodos, oldTodo, messageKey } = ctx;
      closeSnackbar(messageKey);
      const errorMessage = mapError(error);
      enqueueSnackbar(
        `Ops! There was an error on editing todo: ${errorMessage}`,
        {
          variant: &apos;error&apos;,
        }
      );
      client.setQueryData([QUERY_KEY.todos, todo.id], oldTodo);
      client.setQueryData&amp;lt;Todo[]&amp;gt;([QUERY_KEY.todos], oldTodos);
    },
  });

  return editTodo;
};

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, in the mutate event, the code creates a toast for the user, which indicates that everything has gone in the right way and after that, the code takes the current state, returns it and update the state with the new values. The return is important because it permits getting this data in the &lt;code&gt;onError&lt;/code&gt; event in case of failure. The &lt;code&gt;onError&lt;/code&gt; event, as you can notice, handles the restoration of the state, removes the success toast and shows a new one with the error message. This part is crucial if you want to handle an optimistic update because it gives feedback to the user in case of failure.&lt;/p&gt;
&lt;p&gt;Last but not least, you can also handle the &lt;code&gt;onSuccess&lt;/code&gt; event if you want to invalidate a query after the mutation or for some other motivation. The &lt;code&gt;onSuccess&lt;/code&gt; is not required always but depends on your case.&lt;/p&gt;
&lt;p&gt;Ok, I think now you have an idea of how the optimistic update works in react query, but if you want to dive into it check out my youtube video too.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=IwkhNxIyyzA&quot;&gt;https://www.youtube.com/watch?v=IwkhNxIyyzA&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think thats all from this article; I hope you enjoyed this content!&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;br /&gt;
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the code of the video &lt;a href=&quot;https://github.com/Puppo/learning-react-query/tree/09-optimistic-update&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rahuulmiishra?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Rahul Mishra&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>react</category><category>reactquery</category><category>reacthooks</category></item><item><title>React Query - Keys &amp; Prefetching</title><link>https://delpuppo.net/blog/react-query/react-query-keys-prefetching/</link><guid isPermaLink="true">https://delpuppo.net/blog/react-query/react-query-keys-prefetching/</guid><description>Hey Folks, Today I want to share two important things if you are using ReactQuery. The first is how...</description><pubDate>Wed, 03 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey Folks, Today I want to share two important things if you are using ReactQuery. The first is how the keys are composed, and the second is how to prefetch data to reduce the user&apos;s wasted time. So let&apos;s start 🚀&lt;/p&gt;
&lt;h2&gt;Keys&lt;/h2&gt;
&lt;p&gt;As you have already learned in this series, React query uses the keys to save the data of a specific API. And these keys must be unique for each specific API. When you create a &lt;code&gt;useQuery&lt;/code&gt; hook, the first parameter is the query&apos;s key, which is an array. This array is used to compose the key, and it is in charge of you creating the key in the right way for your case. As said before, the key is an array, and in this way, you can create a key composed of different data.&lt;br /&gt;
So, for instance, you can have a key for the list of the todos and a key for the detail of a specific todo (&lt;code&gt;[&quot;todos&quot;]&lt;/code&gt; and &lt;code&gt;[&quot;todo&quot;, 2]&lt;/code&gt;.)&lt;br /&gt;
As you can notice, you can put in the key whatever you want, string number or boolean; it is completely on your side; the important thing you must remember every time is that each key must be unique. This concept, and the key you choose, are also important if you want to prefetch the data because you must use the same key to save the data prefetched in the react query state.&lt;/p&gt;
&lt;h2&gt;Prefetching&lt;/h2&gt;
&lt;p&gt;In some scenarios, loading the data before the user asks for it could be interesting. This improves the user experience and reduces the waste time for them. But how can you do that with react query?&lt;br /&gt;
First, you need to use the &lt;code&gt;QueryClient&lt;/code&gt; object that exposes the &lt;code&gt;prefetchQuery&lt;/code&gt; method.&lt;br /&gt;
This method accepts two parameters: the query&apos;s key and the fetch request.&lt;br /&gt;
In this way, you can handle a simple but powerful prefetching flow with few lines of code. Let&apos;s take a look at this example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export const useTodos = (): UseTodos =&amp;gt; {
  const client = useQueryClient();

  const [userFilter, setUserFilter] = useState&amp;lt;number | null&amp;gt;(null);

  const filterTodoByAssignee = useCallback(
    (todos: Todo[]) =&amp;gt; {
      if (!userFilter) return todos;
      return todos.filter((todo) =&amp;gt; todo.assigneeId === userFilter);
    },
    [userFilter]
  );

  const {
    data: todos = [],
    isLoading,
    isFetching,
    error,
  } = useQuery([QUERY_KEY.todos], fetchTodos, {
    refetchOnWindowFocus: false,
    retry: 2,
    select: filterTodoByAssignee,
    onSuccess: (data) =&amp;gt; {
      data.forEach((todo) =&amp;gt; {
        client.prefetchQuery([QUERY_KEY.todos, id], () =&amp;gt; fetchTodo(id));
      });
    },
  });

  return {
    todos,
    isLoading,
    isFetching,
    error: mapError(error),
    setUserFilter,
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, in this example in the &lt;code&gt;onSuccess&lt;/code&gt; hook, the prefetch feature starts to load the data of every todo in the result of the list. That allows React Query to save the data in the storage and reuse them in the future when the application asks for that data. For instance, in a todo detail hook like this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const fetchTodo = async (id: Todo[&apos;id&apos;]): Promise&amp;lt;Todo&amp;gt; =&amp;gt; {
  const response = await fetch(`api/tasks/${id}`);
  if (!response.ok) {
    throw new ResponseError(`Failed to fetch todo with id ${id}`, response);
  }
  return await response.json();
};

export const useGetTodoById = (id: Todo[&apos;id&apos;]): UseTodo =&amp;gt; {
  const {
    data: todo = null,
    isLoading,
    error,
  } = useQuery([QUERY_KEY.todos, id], () =&amp;gt; fetchTodo(id), {
    refetchOnMount: false,
    refetchOnWindowFocus: false,
    retry: 2,
  });

  return {
    todo,
    isLoading,
    error: mapError(error),
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the key of this &lt;code&gt;useQuery&lt;/code&gt; is the same as the key in the prefetch example, and in this way, ReactQuery is able to understand if the data are already loaded or not.&lt;br /&gt;
As you can imagine, with this simple feature, you can improve the quality of your application and maybe prefetch some data that could take too long to load.&lt;/p&gt;
&lt;p&gt;Ok, I think you have a great idea of how key and prefetching work in React Query.&lt;br /&gt;
To learn more about them, check out also my Youtube video available here 👇&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=svvx-pl_hTE&quot;&gt;https://www.youtube.com/watch?v=svvx-pl_hTE&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think thats all from this article; I hope you enjoyed this content!&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;br /&gt;
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the code of the video &lt;a href=&quot;https://github.com/Puppo/learning-react-query/tree/08-query-key-and-prefetch-data&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rahuulmiishra?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Rahul Mishra&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>react</category><category>reactquery</category><category>reacthooks</category></item><item><title>React Query - Enable Query</title><link>https://delpuppo.net/blog/react-query/react-query-enable-query/</link><guid isPermaLink="true">https://delpuppo.net/blog/react-query/react-query-enable-query/</guid><description>Hey folks, Do you know that you can enable or disable a query in react query? Noooo! Ok, it&apos;s time to...</description><pubDate>Wed, 26 Apr 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey folks,&lt;br /&gt;
Do you know that you can enable or disable a query in react query? Noooo! Ok, it&apos;s time to learn it!&lt;/p&gt;
&lt;p&gt;Some specific hooks must be enabled only if there are some data in the application; for instance, some queries must run only if the users are logged in.&lt;br /&gt;
To solve this problem, the &lt;code&gt;useQuery&lt;/code&gt; hooks accept an option called &lt;code&gt;enabled&lt;/code&gt; that accepts a boolean to determine if a condition is true or false.&lt;br /&gt;
Let&apos;s take a look at this example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { useQuery } from &apos;@tanstack/react-query&apos;;
import { QUERY_KEY } from &apos;src/app/constants/queryKeys&apos;;
import { Todo } from &apos;src/app/models&apos;;
import { User, useUser } from &apos;../../../../auth/useUser&apos;;
import { ResponseError } from &apos;../../../../utils/Errors/ResponseError&apos;;

const fetchTodos = async (user: User): Promise&amp;lt;Todo[]&amp;gt; =&amp;gt; {
  const response = await fetch(`api/tasks?assigneeId=${user.user.id}`, {
    headers: {
      Authorization: `Bearer ${user.accessToken}`,
    },
  });
  if (!response.ok) {
    throw new ResponseError(&apos;Failed to fetch my todos&apos;, response);
  }
  return await response.json();
};

interface UseMyTodos {
  todos: Todo[];
  error?: string;
}

function mapError(error: unknown | undefined): undefined | string {
  if (!error) return undefined;
  if (error instanceof ResponseError) return error.response.statusText;
  if (error instanceof Error) return error.message;
  return &apos;Unknown error&apos;;
}

export const useMyTodos = (): UseMyTodos =&amp;gt; {
  const { user } = useUser();

  const { data: todos = [], error } = useQuery(
    [QUERY_KEY.myTodos],
    () =&amp;gt; fetchTodos(user!),
    {
      refetchOnWindowFocus: false,
      retry: 2,
      enabled: !!user,
    }
  );

  return {
    todos,
    error: mapError(error),
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, in this case, a custom hook calls the API and gets all the todos assigned to the current users.&lt;br /&gt;
The key point of this example stands in the enabled option. As you can see, this &lt;code&gt;useQuery&lt;/code&gt; is called only if there is a user; else, the query is stopped.&lt;br /&gt;
This feature permits developers to be sure to call a specific API only if a condition is satisfied, preventing a bad API request.&lt;br /&gt;
This feature is pretty simple but very powerful, as you can imagine!&lt;/p&gt;
&lt;p&gt;To find out more about the &lt;code&gt;enabled&lt;/code&gt; option take a look at my youtube video about it&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=5JSD_b2slJs&quot;&gt;https://www.youtube.com/watch?v=5JSD_b2slJs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ok, that&apos;s all from the enabled option.&lt;/p&gt;
&lt;p&gt;I hope you enjoyed this content!&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;/p&gt;
&lt;p&gt;Bye Bye 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the code of the video &lt;a href=&quot;https://github.com/Puppo/learning-react-query/tree/07-enable-query&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rahuulmiishra?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Rahul Mishra&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>react</category><category>reactquery</category><category>reacthooks</category></item><item><title>React Query - Filter Your Data</title><link>https://delpuppo.net/blog/react-query/react-query-filter-your-data/</link><guid isPermaLink="true">https://delpuppo.net/blog/react-query/react-query-filter-your-data/</guid><description>Hey folks, Did you know that you can filter your data in react query? Noooo! Ok, it&apos;s time to learn...</description><pubDate>Wed, 19 Apr 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey folks,&lt;br /&gt;
Did you know that you can filter your data in react query? Noooo! Ok, it&apos;s time to learn it!&lt;/p&gt;
&lt;p&gt;To filter the data in your &lt;code&gt;useQuery&lt;/code&gt; hook, you have to handle the &lt;code&gt;select&lt;/code&gt; option. This option accepts a function that is used to filter the data.&lt;br /&gt;
The function has one parameter, and this parameter contains the result of the query; the scope of the select function is to manipulate the query&apos;s result and returns a new result that respects some rules.&lt;/p&gt;
&lt;p&gt;Let&apos;s take a look at this example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { useQuery } from &apos;@tanstack/react-query&apos;;
import { Dispatch, SetStateAction, useCallback, useState } from &apos;react&apos;;
import { QUERY_KEY } from &apos;src/app/constants/queryKeys&apos;;
import { Todo } from &apos;src/app/models&apos;;
import { ResponseError } from &apos;../../../../utils/Errors/ResponseError&apos;;

const fetchTodos = async (): Promise&amp;lt;Todo[]&amp;gt; =&amp;gt; {
  const response = await fetch(&apos;api/tasks&apos;);
  if (!response.ok) {
    throw new ResponseError(&apos;Failed to fetch todos&apos;, response);
  }
  return await response.json();
};

interface UseTodos {
  todos: Todo[];
  isLoading: boolean;
  isFetching: boolean;
  error?: string;
  setUserFilter: Dispatch&amp;lt;SetStateAction&amp;lt;number | null&amp;gt;&amp;gt;;
}

function mapError(error: unknown | undefined): undefined | string {
  if (!error) return undefined;
  if (error instanceof ResponseError) return error.response.statusText;
  if (error instanceof Error) return error.message;
  return &apos;Unknown error&apos;;
}

export const useTodos = (): UseTodos =&amp;gt; {
  const [userFilter, setUserFilter] = useState&amp;lt;number | null&amp;gt;(null);

  const filterTodoByAssignee = useCallback(
    (todos: Todo[]) =&amp;gt; {
      if (!userFilter) return todos;
      return todos.filter((todo) =&amp;gt; todo.assigneeId === userFilter);
    },
    [userFilter]
  );

  const {
    data: todos = [],
    isLoading,
    isFetching,
    error,
  } = useQuery([QUERY_KEY.todos], fetchTodos, {
    refetchOnWindowFocus: false,
    retry: 2,
    select: filterTodoByAssignee,
  });

  return {
    todos,
    isLoading,
    isFetching,
    error: mapError(error),
    setUserFilter,
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, this example has some key points to analyse.&lt;br /&gt;
First, the &lt;code&gt;filterTodoByAssignee&lt;/code&gt; function is the select function passed to the &lt;code&gt;useQuery&lt;/code&gt; hook. This function checks the &lt;code&gt;userFilter&lt;/code&gt; state, and if it is empty, the function returns the entire list; else, it filters the result and returns only the todos that have the &lt;code&gt;assigneeId&lt;/code&gt; that matches with the &lt;code&gt;userFilter&lt;/code&gt; value.&lt;br /&gt;
It&apos;s important, in this case, to use the &lt;code&gt;useCallback&lt;/code&gt; hook and pass to it the right dependencies to prevent a decrease in the performance of the application.&lt;br /&gt;
Then another important thing is the &lt;code&gt;setUserFilter&lt;/code&gt; function that it&apos;s used to set the &lt;code&gt;userFilter&lt;/code&gt; value. This function is exposed by the custom hook to permit the users to change the filter.&lt;/p&gt;
&lt;p&gt;And that&apos;s all; in these two simple steps, you have a &lt;code&gt;select&lt;/code&gt; function to filter the dataset got from the query. You can use this solution also to create a client-side pagination in your react query application (for the server-side pagination, there will be a post in the future)&lt;/p&gt;
&lt;p&gt;If you want to find out more, check my youtube video about this topic&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=H4l1QAA4Dxw&quot;&gt;https://www.youtube.com/watch?v=H4l1QAA4Dxw&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ok, that&apos;s all from the select option!&lt;/p&gt;
&lt;p&gt;I hope you enjoyed this content!&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;/p&gt;
&lt;p&gt;Bye Bye 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the code of the video &lt;a href=&quot;https://github.com/Puppo/learning-react-query/tree/06-query-filters&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rahuulmiishra?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Rahul Mishra&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>react</category><category>reactquery</category><category>reacthooks</category></item><item><title>React Query - Authentication Flow</title><link>https://delpuppo.net/blog/react-query/react-query-authentication-flow/</link><guid isPermaLink="true">https://delpuppo.net/blog/react-query/react-query-authentication-flow/</guid><description>Every application should handle an authentication flow; in this article, you&apos;ll learn how to build an...</description><pubDate>Wed, 12 Apr 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Every application should handle an authentication flow; in this article, you&apos;ll learn how to build an authentication flow in your React Application with React Query.&lt;/p&gt;
&lt;h2&gt;Sign Up&lt;/h2&gt;
&lt;p&gt;The first step to build an authentication flow is the sign-up action. As you have already learned in this series, you should build a mutation to do this action. A possible solution could be this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;async function signUp(email: string, password: string): Promise&amp;lt;User&amp;gt; {
  const response = await fetch(&apos;/api/auth/signup&apos;, {
    method: &apos;POST&apos;,
    headers: {
      &apos;Content-Type&apos;: &apos;application/json&apos;
    },
    body: JSON.stringify({ email, password })
  })
  if (!response.ok)
    throw new ResponseError(&apos;Failed on sign up request&apos;, response);

  return await response.json();
}

type IUseSignUp = UseMutateFunction&amp;lt;User, unknown, {
  email: string;
  password: string;
}, unknown&amp;gt;

export function useSignUp(): IUseSignUp {
  const queryClient = useQueryClient();
  const navigate = useNavigate();
  const { enqueueSnackbar } = useSnackbar();

  const { mutate: signUpMutation } = useMutation&amp;lt;User, unknown, { email: string, password: string }, unknown&amp;gt;(
    ({
      email,
      password
    }) =&amp;gt; signUp(email, password), {
    onSuccess: (data) =&amp;gt; {
      // TODO: save the user in the state
      navigate(&apos;/&apos;);
    },
    onError: (error) =&amp;gt; {
      enqueueSnackbar(&apos;Ops.. Error on sign up. Try again!&apos;, {
        variant: &apos;error&apos;
      });
    }
  });

  return signUpMutation
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By creating a mutation like that, you build the signUp in a very simple and clear way.&lt;br /&gt;
Now using the &lt;code&gt;useSignUp&lt;/code&gt; hook, you can get the mutation and call the signUp request to create a new user in your system. As you can notice, the code is pretty simple; the &lt;code&gt;signUp&lt;/code&gt; method calls the API to post the new user&apos;s data and return the user data saved in the database. Then using the &lt;code&gt;useMutation&lt;/code&gt; hook, you can build the mutation to handle the signUp action. If everything goes ok, the &lt;code&gt;onSuccess&lt;/code&gt; hook calls the navigation to the home page; otherwise, the &lt;code&gt;onError&lt;/code&gt; hook shows a toast with an error.&lt;br /&gt;
In the code, there is a TODO that indicates something missing; we&apos;ll get back to this line in the future of this post.&lt;/p&gt;
&lt;h2&gt;Sign In&lt;/h2&gt;
&lt;p&gt;The second step to build if you are building an authentication flow is SignIn. In this case, SignIn is pretty similar to SignUp; the only things that change are the endpoint and the scope of the hook.&lt;br /&gt;
So the code can be this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;async function signIn(email: string, password: string): Promise&amp;lt;User&amp;gt; {
  const response = await fetch(&apos;/api/auth/signin&apos;, {
    method: &apos;POST&apos;,
    headers: {
      &apos;Content-Type&apos;: &apos;application/json&apos;
    },
    body: JSON.stringify({ email, password })
  })
  if (!response.ok)
    throw new ResponseError(&apos;Failed on sign in request&apos;, response);

  return await response.json();
}

type IUseSignIn = UseMutateFunction&amp;lt;User, unknown, {
  email: string;
  password: string;
}, unknown&amp;gt;

export function useSignIn(): IUseSignIn {
  const queryClient = useQueryClient();
  const navigate = useNavigate();
  const { enqueueSnackbar } = useSnackbar();

  const { mutate: signInMutation } = useMutation&amp;lt;User, unknown, { email: string, password: string }, unknown&amp;gt;(
    ({
      email,
      password
    }) =&amp;gt; signIn(email, password), {
    onSuccess: (data) =&amp;gt; {
      // TODO: save the user in the state
      navigate(&apos;/&apos;);
    },
    onError: (error) =&amp;gt; {
      enqueueSnackbar(&apos;Ops.. Error on sign in. Try again!&apos;, {
        variant: &apos;error&apos;
      });
    }
  });

  return signInMutation
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I don&apos;t want to spend much time describing this hook because it is very similar to the SignUp but only with the references for the SignIn. Also in this case, there is a TODO that we&apos;ll remove in the future of the post.&lt;/p&gt;
&lt;h2&gt;The user&lt;/h2&gt;
&lt;p&gt;The core part of an authentication flow is where you save the user in the state. To do that, in this case, the best way is to create a new hook called &lt;code&gt;useUser&lt;/code&gt; which is the owner of the user data.&lt;br /&gt;
The &lt;code&gt;useUser&lt;/code&gt; hook must have the user&apos;s data, and it has to save the user&apos;s data in the local storage and retrieve them when the user refreshes the page or gets back in the future.&lt;br /&gt;
Let&apos;s start with the code that handles the local storage. Typically, this code is created with small functions with a specific goal like the next.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { User } from &apos;./useUser&apos;;

const USER_LOCAL_STORAGE_KEY = &apos;TODO_LIST-USER&apos;;

export function saveUser(user: User): void {
  localStorage.setItem(USER_LOCAL_STORAGE_KEY, JSON.stringify(user));
}

export function getUser(): User | undefined {
  const user = localStorage.getItem(USER_LOCAL_STORAGE_KEY);
  return user ? JSON.parse(user) : undefined;
}

export function removeUser(): void {
  localStorage.removeItem(USER_LOCAL_STORAGE_KEY);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this way, you can create a small module that handles all the local storage functions for the user.&lt;/p&gt;
&lt;p&gt;Now it&apos;s time to see how you can build the &lt;code&gt;useUser&lt;/code&gt; hook.&lt;br /&gt;
Let&apos;s start with the code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;async function getUser(user: User | null | undefined): Promise&amp;lt;User | null&amp;gt; {
  if (!user) return null;
  const response = await fetch(`/api/users/${user.user.id}`, {
    headers: {
      Authorization: `Bearer ${user.accessToken}`
    }
  })
  if (!response.ok)
    throw new ResponseError(&apos;Failed on get user request&apos;, response);

  return await response.json();
}

export interface User {
  accessToken: string;
  user: {
    email: string;
    id: number;
  }
}

interface IUseUser {
  user: User | null;
}

export function useUser(): IUseUser {
  const { data: user } = useQuery&amp;lt;User | null&amp;gt;(
    [QUERY_KEY.user],
    async (): Promise&amp;lt;User | null&amp;gt; =&amp;gt; getUser(user),
    {
      refetchOnMount: false,
      refetchOnWindowFocus: false,
      refetchOnReconnect: false,
      initialData: userLocalStorage.getUser,
      onError: () =&amp;gt; {
        userLocalStorage.removeUser();
      }
    });

  useEffect(() =&amp;gt; {
    if (!user) userLocalStorage.removeUser();
    else userLocalStorage.saveUser(user);
  }, [user]);

  return {
    user: user ?? null,
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;getUser&lt;/code&gt; function is simple; it provides the HTTP request to get the user info; if the user is null, return null otherwise, it calls the HTTP endpoint.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;useQuery&lt;/code&gt; hook is similar to the others seen before, but there are two new configurations to understand.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;refetchOnMount&lt;/strong&gt; : this option is important to prevent the hook reloads the data each time it is used&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;initialData&lt;/strong&gt; : this option is used to load the data from the local storage; the initialData accepts a function that returns the initial value; if the initial value is defined, react query uses this value to refresh the data.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now you have all the blocks of the authentication flow, but it&apos;s time to link &lt;code&gt;useSignUp&lt;/code&gt; and &lt;code&gt;useSignIn&lt;/code&gt; with the &lt;code&gt;useUser&lt;/code&gt; hook.&lt;br /&gt;
Using the &lt;a href=&quot;https://tanstack.com/query/v4/docs/react/reference/QueryClient&quot;&gt;QueryClient&lt;/a&gt; you can set the data of a specific query by the &lt;a href=&quot;https://tanstack.com/query/v4/docs/react/reference/QueryClient#queryclientsetquerydata&quot;&gt;setQueryData&lt;/a&gt; function.&lt;br /&gt;
So the previous TODOs comments change in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export function useSignUp(): IUseSignUp {
  const queryClient = useQueryClient();
  const navigate = useNavigate();
  const { enqueueSnackbar } = useSnackbar();

  const { mutate: signUpMutation } = useMutation&amp;lt;User, unknown, { email: string, password: string }, unknown&amp;gt;(
    ({
      email,
      password
    }) =&amp;gt; signUp(email, password), {
    onSuccess: (data) =&amp;gt; {
      queryClient.setQueryData([QUERY_KEY.user], data);
      navigate(&apos;/&apos;);
    },
    onError: (error) =&amp;gt; {
      enqueueSnackbar(&apos;Ops.. Error on sign up. Try again!&apos;, {
        variant: &apos;error&apos;
      });
    }
  });

  return signUpMutation
}


export function useSignIn(): IUseSignIn {
  const queryClient = useQueryClient();
  const navigate = useNavigate();
  const { enqueueSnackbar } = useSnackbar();

  const { mutate: signInMutation } = useMutation&amp;lt;User, unknown, { email: string, password: string }, unknown&amp;gt;(
    ({
      email,
      password
    }) =&amp;gt; signIn(email, password), {
    onSuccess: (data) =&amp;gt; {
      queryClient.setQueryData([QUERY_KEY.user], data);
      navigate(&apos;/&apos;);
    },
    onError: (error) =&amp;gt; {
      enqueueSnackbar(&apos;Ops.. Error on sign in. Try again!&apos;, {
        variant: &apos;error&apos;
      });
    }
  });

  return signInMutation
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With two simple lines of code, you can set the user in the &lt;code&gt;useUser&lt;/code&gt; state because the key used to set the query data is the same as the &lt;code&gt;useUser&lt;/code&gt;.&lt;br /&gt;
Then, with an &lt;code&gt;useEffect&lt;/code&gt; in the &lt;code&gt;useUser&lt;/code&gt; hook, you can remove or set the user data in the local storage when the user changes&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export function useUser(): IUseUser {
  const { data: user } = useQuery&amp;lt;User | null&amp;gt;(
    [QUERY_KEY.user],
    async (): Promise&amp;lt;User | null&amp;gt; =&amp;gt; getUser(user),
    {
      refetchOnMount: false,
      refetchOnWindowFocus: false,
      refetchOnReconnect: false,
      initialData: userLocalStorage.getUser,
      onError: () =&amp;gt; {
        userLocalStorage.removeUser();
      }
    });

  useEffect(() =&amp;gt; {
    if (!user) userLocalStorage.removeUser();
    else userLocalStorage.saveUser(user);
  }, [user]);

  return {
    user: user ?? null,
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To complete the authentication flow, the only missing thing is the logout.&lt;br /&gt;
You can build it with a custom hook called &lt;code&gt;useSignOut&lt;/code&gt;; its implementation is straightforward and could be done in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { useQueryClient } from &apos;@tanstack/react-query&apos;;
import { useCallback } from &apos;react&apos;;
import { useNavigate } from &apos;react-router-dom&apos;;
import { QUERY_KEY } from &apos;../constants/queryKeys&apos;;

type IUseSignOut = () =&amp;gt; void

export function useSignOut(): IUseSignOut {
  const queryClient = useQueryClient();
  const navigate = useNavigate();

  const onSignOut = useCallback(() =&amp;gt; {
    queryClient.setQueryData([QUERY_KEY.user], null);
    navigate(&apos;/auth/sign-in&apos;);
  }, [navigate, queryClient])

  return onSignOut
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, the hook returns a simple function that clears the value in the user state and navigates to the &lt;code&gt;sign-in&lt;/code&gt; page.&lt;/p&gt;
&lt;p&gt;Ok, perfect. Now you have all the notions of building an authentication flow with React Query, but If you want to find out more, watch my youtube video about authentication with React Query&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=JNoiAumC94g&quot;&gt;https://www.youtube.com/watch?v=JNoiAumC94g&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ok, that&apos;s all from authentication.&lt;/p&gt;
&lt;p&gt;I hope you enjoyed this content!&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;/p&gt;
&lt;p&gt;Bye Bye 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the code of the video &lt;a href=&quot;https://github.com/Puppo/learning-react-query/tree/05-auth&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rahuulmiishra?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Rahul Mishra&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>react</category><category>reactquery</category><category>reacthooks</category></item><item><title>Playwright - UI Mode</title><link>https://delpuppo.net/blog/playwright/playwright-ui-mode/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-ui-mode/</guid><description>Hi folks, In release 1.32, Playwright released a new cool feature for us, the UI Mode! This feature...</description><pubDate>Thu, 06 Apr 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi folks,&lt;br /&gt;
In release &lt;a href=&quot;https://playwright.dev/docs/release-notes#version-132&quot;&gt;1.32&lt;/a&gt;, Playwright released a new cool feature for us, the UI Mode!&lt;/p&gt;
&lt;p&gt;This feature is still in beta yet, but you can use it by adding a simple option in the CLI &lt;code&gt;--ui&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ npx playwright test --ui
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result of this command is a new window in your display!&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Using this view, you can run and debug your test. But let&apos;s dive into it.&lt;br /&gt;
The view is split into two parts: the left part contains the list of the tests, and the right part is the crucial view to check and debug the tests. If you are familiar with the Playwright tracer, the right section is similar to the tracer view.&lt;/p&gt;
&lt;p&gt;But what can you do with this view?&lt;br /&gt;
First, you can run one or many tests using the run button at the right of each test or group of tests.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Playwright runs the tests by clicking this button, and you can see the result. A green tick means the test is ok, and a red icon with a circle X means there is an error in the test.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Now if you click on one of the tests in the right section, you can see what happened during its execution.&lt;br /&gt;
In this case, let&apos;s dive into the wrong test.&lt;br /&gt;
In the top section, you can see the timeline of the test; you can go over it with the mouse and see all the browser views during the execution.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In the action tab, you can find all the actions done by the test, for instance: the page creation, the navigation, each click on the page and so on. You can navigate in the history by clicking on one of these actions, and each time you click the action, the panel on the right shows the view at that specific moment. In this way, you can understand what happened during the test execution.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In the bottom bar, you can access different views: Source, Console, Network, and Log.&lt;br /&gt;
I think the last three views are pretty simple, and I want to focus on the Source view.&lt;br /&gt;
In the Source view, you can see all the code used by Playwright to run the test, and if you click on one of the actions, Playwright highlights the line of code that runs that action. If your test is wrong, Playwright shows you the error in the specific line of code where the error is thrown. In this way, you can immediately see the mistake and try fixing it.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The last cool feature introduced in this view is the possibility to open the Source code directly from the view! If you click the icon at the right of the Run icon, Playwright opens the file using Visual Studio Code.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Last but not least, Playwright keeps syncing your codebase with the Playwright UI Runner, so in this way, you can change and fix errors and retry the test immediately.&lt;/p&gt;
&lt;p&gt;If you want to find out more or watch the Playwright UI Runner on working, check out my Youtube video.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ErkRgqmHCmc&quot;&gt;https://www.youtube.com/watch?v=ErkRgqmHCmc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I think this solution and the integration of Playwright with VsCode are awesome, and Playwright is changing the Developer Experience in the best possible way!&lt;/p&gt;
&lt;p&gt;Ok, that&apos;s all folks!&lt;br /&gt;
I hope you enjoyed this content, and now your testing phase is more comfortable and easier!&lt;/p&gt;
&lt;p&gt;See you later!&lt;br /&gt;
Bye Bye 👋&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>e2e</category></item><item><title>React Query - DevTools</title><link>https://delpuppo.net/blog/react-query/react-query-devtools/</link><guid isPermaLink="true">https://delpuppo.net/blog/react-query/react-query-devtools/</guid><description>Hey Folks, In this post, you&apos;ll learn how to debug and check whatever happens in your React Query...</description><pubDate>Wed, 05 Apr 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey Folks,&lt;/p&gt;
&lt;p&gt;In this post, you&apos;ll learn how to debug and check whatever happens in your React Query application. It&apos;s normal when you begin to learn or use a tool; check the tools around it to understand the developer experience so you can decide whether to continue with it. The React query team knows that and has decided to build a tool to help the developer that wants to work with React Query.&lt;br /&gt;
This tool is called &lt;code&gt;react-query-devtools&lt;/code&gt; and you can install it in a simple step.&lt;br /&gt;
Open your terminal and type&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ npm i @tanstack/react-query-devtools
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, in your project, you can use it and get all the info required to debug your application.&lt;/p&gt;
&lt;p&gt;This tool is simple to use. In your application, you must import it and render it where you render the &lt;code&gt;ReactQueryProvider&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { QueryClientProvider } from &apos;@tanstack/react-query&apos;;
import { ReactQueryDevtools } from &apos;@tanstack/react-query-devtools&apos;;
import React from &quot;react&quot;;
import { queryClient } from &apos;./react-query/client&apos;;
import Router from &apos;./Router&apos;;

function App() {
  return (
    &amp;lt;React.StrictMode&amp;gt;
      &amp;lt;QueryClientProvider client={queryClient}&amp;gt;
        ...
        &amp;lt;ReactQueryDevtools /&amp;gt;
      &amp;lt;/QueryClientProvider&amp;gt;
    &amp;lt;/React.StrictMode&amp;gt;
  );
}
export default App;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Easy peasy, no?&lt;br /&gt;
With ReactQueryDevtools, you don&apos;t have to pay attention to the environment to render or not the component because it provides it by default. It renders the component only if the condition &lt;code&gt;process.env.NODE_ENV === &apos;development&apos;&lt;/code&gt; is true.&lt;br /&gt;
You can customize the component or force its render also in production mode if you want. To find out more about these topics, you can check the &lt;a href=&quot;https://tanstack.com/query/latest/docs/react/devtools&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The benefit of using this component in your application is that it allows seeing what happens in ReactQuery at runtime. You can check the data saved in the state, how many application parts use the different queries, etc. You can also reset the state or remove part of it to re-fetch the data.&lt;/p&gt;
&lt;p&gt;Yeap, it exposes many good features to debug and check your React Query application, and it is a good tool for every developer that works with React Query. Here you can find an example of ReactQueryDevtool at work&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;If you want to find out more, watch my Youtube video about React Query Devtool to see it in action.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://youtu.be/qXycRUetOX4&quot;&gt;https://youtu.be/qXycRUetOX4&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ok, that&apos;s all! I think you have an idea of what React Query Devtools is and how you can integrate it into your application!&lt;br /&gt;
I hope you enjoyed this content!&lt;/p&gt;
&lt;p&gt;See you soon folks
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the code of the video &lt;a href=&quot;https://github.com/Puppo/learning-react-query/tree/04-devtools&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rahuulmiishra?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Rahul Mishra&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>react</category><category>reactquery</category><category>reacthooks</category></item><item><title>OramaSearch, a full-text search in your React application</title><link>https://delpuppo.net/blog/oramasearch-a-full-text-search-in-your-react-application/</link><guid isPermaLink="true">https://delpuppo.net/blog/oramasearch-a-full-text-search-in-your-react-application/</guid><description>In some applications, you need to create a full-text search to improve the search of data. In some...</description><pubDate>Thu, 30 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In some applications, you need to create a full-text search to improve the search of data. In some scenarios, you build this using an API and leave the problem to the backend. But in other cases, you need to guarantee the feature without an internet connection, or you are building a hybrid application, or you need to reduce these kinds of searches directly in the browser to reduce the computation cost in the server. A simple example could be to perform a search on your blog to see which articles respect some criteria.&lt;br /&gt;
To do this, in the last period, &lt;a href=&quot;https://oramasearch.com/&quot;&gt;Orama Search&lt;/a&gt; has born. A simple npm library that allows you to create a &quot;small&quot; typed database in your browser (and not only) and exposes a simple method that permits you to search data in this database.&lt;br /&gt;
So, in this article, you&apos;ll discover how to use Orama Search in your React application and learn how it is easy to integrate it into your next applications.&lt;/p&gt;
&lt;p&gt;Before starting a quick explanation of the application, because I don&apos;t want to cover all the processes in this article but only the Orama integration.&lt;br /&gt;
The application is a simple React page where you can search for one or more Italian cities by a term. The terms could search the cities by names or by regions.&lt;br /&gt;
The application on startup loads all the possible cities and create an Orama database in the browser. Then you can search using the form the city you prefer.&lt;br /&gt;
I wrapped the Orama logic inside of a &lt;a href=&quot;https://react.dev/reference/react/createContext&quot;&gt;React Context&lt;/a&gt;, and you can interact with it using two hooks.&lt;/p&gt;
&lt;p&gt;Here you can find the result&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;If you want to read this article with the full code of the application, you can find it &lt;a href=&quot;https://github.com/Puppo/orama-search-getting-started&quot;&gt;in the GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;N.B. in this article, I&apos;ll use&lt;/em&gt; &lt;a href=&quot;https://www.npmjs.com/package/@antfu/ni&quot;&gt;&lt;em&gt;ni&lt;/em&gt;&lt;/a&gt; &lt;em&gt;instead of npm, yarn or pnpm, but you can use whichever you prefer without any problems.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;The first step to use Orama in your application is to install it.&lt;br /&gt;
It&apos;s a piece of cake; in your terminal type:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ni @orama/orama
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think this step doesn&apos;t need a big explanation. But this is the door to start using Orama in your application. With this command, now in your &lt;code&gt;node_modules&lt;/code&gt;, you can find the Orama packages, and now it&apos;s time to start using it!&lt;/p&gt;
&lt;h2&gt;Create Database&lt;/h2&gt;
&lt;p&gt;First of all, to use Orama you have to create a database. To do that, Orama exposes a method called &lt;code&gt;create&lt;/code&gt;. This method accepts a schema that describes the database structure and some options to configure the database.&lt;br /&gt;
For this example, in addition to the schema, I want to show you how you can work with a different language (Italian, in this case) and how you can configure Orama to do that. Orama, to handle this process, uses &lt;a href=&quot;https://github.com/words/stemmer&quot;&gt;stemmer&lt;/a&gt; out-of-the-box.&lt;br /&gt;
So to create a simple database in this case and to move your first steps with Orama, you can go to the folder &lt;code&gt;src/core/useOrama&lt;/code&gt; where you&apos;ll find all the code to handle Orama in your application.&lt;br /&gt;
Let&apos;s start from the &lt;code&gt;src/core/useOrama/context.ts&lt;/code&gt; file&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Orama, Schema } from &quot;@orama/orama&quot;;
import { createContext } from &quot;react&quot;;
import { SchemaToTypes } from &quot;./types&quot;;

export type OramaContext&amp;lt;S extends Schema = any&amp;gt; = {
  isCreated: boolean;
  isIndexed: boolean;
  db?: Orama;
  setData: (data: SchemaToTypes&amp;lt;S&amp;gt;[]) =&amp;gt; Promise&amp;lt;void&amp;gt;;
};

export const OramaContext = createContext&amp;lt;OramaContext&amp;gt;({
  isCreated: false,
  isIndexed: false,
  setData: async values =&amp;gt; undefined,
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the context of Orama for this application is simple. Two flags to understand the status of the database, the database and the &lt;code&gt;setData&lt;/code&gt; function to insert the data in the database.&lt;/p&gt;
&lt;p&gt;Now you can move to the OramaProvider inside of the &lt;code&gt;src/core/useOrama/Provider.tsx&lt;/code&gt; file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import {
  create,
  insertMultiple,
  Orama,
  Schema
} from &quot;@orama/orama&quot;;
import {
  PropsWithChildren,
  useCallback,
  useEffect,
  useMemo,
  useState
} from &quot;react&quot;;

import { OramaContext } from &quot;./contex&quot;;
import { SchemaToTypes } from &quot;./types&quot;;

type IOramaProviderProps&amp;lt;S extends Schema&amp;gt; = PropsWithChildren&amp;lt;{
  schema: S
  options?: Omit&amp;lt;Parameters&amp;lt;typeof create&amp;gt;[0], &apos;schema&apos;&amp;gt;
}&amp;gt;

export const OramaProvider = &amp;lt;S extends Schema&amp;gt;({ schema, options, children }: IOramaProviderProps&amp;lt;S&amp;gt;) =&amp;gt; {
  const [isIndexed, setIsIndexed] = useState(false);
  const [orama, setOrama] = useState&amp;lt;Orama | undefined&amp;gt;(undefined)

  const setData = useCallback(async (values: SchemaToTypes&amp;lt;S&amp;gt;[]) =&amp;gt; {
    if (!orama) throw new Error(`Orama database is not created!`)
    setIsIndexed(false);
    await insertMultiple(orama, values);
    setIsIndexed(true);
  }, [orama, setIsIndexed])

  const context = useMemo&amp;lt;OramaContext&amp;gt;(() =&amp;gt; ({
    isCreated: !!orama,
    isIndexed,
    db: orama,
    setData
  }), [setData, orama, isIndexed])

  useEffect(() =&amp;gt; {
    async function init() {
      const db = await create({
        schema,
        ...(options ?? {}),
      });
      setOrama(db);
    }
    init();
  }, []);

  return &amp;lt;OramaContext.Provider value={context}&amp;gt;{children}&amp;lt;/OramaContext.Provider&amp;gt;;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this file, the code starts to be tricker.&lt;br /&gt;
First of all, the provider accepts two properties, the Orama schema and the Orama options. Orama uses these properties to create the database for the application.&lt;br /&gt;
Then the provider does some little things. First, it initializes two states to save the database and the isInidex flag. This flag is used to understand if the data used for the search are saved in the database. Then the provider creates the &lt;code&gt;setData&lt;/code&gt; function used by the application to insert the data in the database. With an effect, it creates the database using the &lt;a href=&quot;https://docs.oramasearch.com/usage/create&quot;&gt;create&lt;/a&gt; method exposed by Orama, and then creates and returns the context using a &lt;code&gt;useMemo&lt;/code&gt; to improve the performance and the &lt;code&gt;OramaContext.Provider&lt;/code&gt; components.&lt;br /&gt;
If you are familiar with React and Javascript/Typescript, I think everything is simple and clear after one or two views of the code.&lt;br /&gt;
The last step is to render the Provider in the application. This is in the &lt;code&gt;src/App.tsx&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { createTheme, ThemeProvider } from &apos;@mui/material/styles&apos;;
import { stemmer } from &apos;@orama/orama/stemmer/it&apos;;

import { CITIES_SCHEMA } from &apos;./core/cities/oramaSchema&apos;;
import { OramaProvider } from &apos;./core/useOrama/Provider&apos;;
import Search from &apos;./page/Search&apos;;

const theme = createTheme();

function App() {
  return &amp;lt;ThemeProvider theme={theme}&amp;gt;
    &amp;lt;OramaProvider schema={CITIES_SCHEMA} options={{
      components: {
        tokenizer: {
          language: &apos;italian&apos;,
          tokenize: stemmer,
          normalizationCache: new Map&amp;lt;string, string&amp;gt;(),
        },
      },
    }}&amp;gt;
      &amp;lt;Search /&amp;gt;
    &amp;lt;/OramaProvider&amp;gt;
  &amp;lt;/ThemeProvider&amp;gt;
}

export default App
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here there are two important things. First, the schema:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export const CITIES_SCHEMA = {
  city: &quot;string&quot;,
  lat: &quot;number&quot;,
  lng: &quot;number&quot;,
  country: &quot;string&quot;,
  iso2: &quot;string&quot;,
  admin_name: &quot;string&quot;,
  capital: &quot;string&quot;,
  population: &quot;number&quot;,
  population_proper: &quot;number&quot;,
} as const;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Second, the Orama configuration. In this case, the configuration imports stemmer and indicates to Orama that the database contains Italian words. Orama works in English by default, but you can use it in other languages. You can find out more in the &lt;a href=&quot;https://docs.oramasearch.com/text-analysis/stemming&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Init Database&lt;/h2&gt;
&lt;p&gt;To initialize the database, you have to see the &lt;code&gt;src/core/useOrama/useOramaSetData.tsx&lt;/code&gt; file.&lt;br /&gt;
This file contains the hook that exposes the function to set the data in the database.&lt;br /&gt;
This is the code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import {
  Schema
} from &quot;@orama/orama&quot;;

import {
  useContext
} from &quot;react&quot;;
import { OramaContext } from &quot;./contex&quot;;

export const useOramaSetData = &amp;lt;S extends Schema = any&amp;gt;() =&amp;gt; {
  const { setData, isCreated }: OramaContext&amp;lt;S&amp;gt; = useContext(OramaContext);
  return {
    canSetData: isCreated,
    setData
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, the hook is pretty simple, get the &lt;code&gt;setData&lt;/code&gt; function and the &lt;code&gt;isCreated&lt;/code&gt; flag, and exposes them. Here the important concept stands in the Provider file where you defined the &lt;code&gt;setData&lt;/code&gt; function.&lt;br /&gt;
Let&apos;s pick this part of the code again&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const setData = useCallback(async (values: SchemaToTypes&amp;lt;S&amp;gt;[]) =&amp;gt; {
  if (!orama) throw new Error(`Orama database is not created!`)
  setIsIndexed(false);
  await insertMultiple(orama, values);
  setIsIndexed(true);
}, [orama, setIsIndexed])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this code, the &lt;code&gt;insertMultiple&lt;/code&gt; function is an important concept for Orama. With the &lt;code&gt;insertMultiple&lt;/code&gt; function, you can insert an array of rows in your database, and then Orama will use these data for future searches. There is also the insert method to insert only one row per time, but you can find more info &lt;a href=&quot;https://docs.oramasearch.com/usage/insert&quot;&gt;in this reference&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then, it&apos;s time to use this method on the Search page to initialize the database with the data.&lt;br /&gt;
To do that, go into the &lt;code&gt;src/Search/index.ts&lt;/code&gt; file, and you can find the import of the hook and how to use it in an &lt;code&gt;effect&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...
import { useOramaSetData } from &apos;../../core/useOrama/useOramaSetData&apos;;
import { getCities } from &apos;../../core/cities/httpCities&apos;;
...

export default function Search() {
...
  const { canSetData, setData } = useOramaSetData&amp;lt;typeof CITIES_SCHEMA&amp;gt;();
...

  useEffect(() =&amp;gt; {
    if (!canSetData) return;

    async function initDb() {
      const cities = await getCities()
      setData(cities)
    }
    initDb()
  }, [canSetData]);

...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, your database is ready to perform the searches 🚀&lt;/p&gt;
&lt;h2&gt;Search in the Database&lt;/h2&gt;
&lt;p&gt;The core part of Orama is the search! Now it&apos;s time to dive into it.&lt;br /&gt;
To handle the search, you&apos;ll create another hook called &lt;code&gt;useOramaSearch&lt;/code&gt;.&lt;br /&gt;
The search is pretty simple in Orama. There is a &lt;code&gt;search&lt;/code&gt; method that accepts the Orama database, the terms to search and some possible options. You can find more &lt;a href=&quot;https://docs.oramasearch.com/usage/search/introduction&quot;&gt;in this reference&lt;/a&gt;.&lt;br /&gt;
The implementation of the search is this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import {
  Schema,
  search as searchWithOrama
} from &quot;@orama/orama&quot;;

import {
  useCallback,
  useContext
} from &quot;react&quot;;
import { OramaContext } from &quot;./contex&quot;;
import { Results } from &quot;./types&quot;;

export const useOramaSearch = &amp;lt;S extends Schema,&amp;gt;() =&amp;gt; {
  const context: OramaContext&amp;lt;S&amp;gt; = useContext(OramaContext);

  const search = useCallback(
    async (term: string, properties: string[] | &apos;*&apos; = &apos;*&apos;): Promise&amp;lt;Results&amp;lt;S&amp;gt;&amp;gt; =&amp;gt; {
      if (!context.db) throw new Error(&quot;Database not ready&quot;);

      const { length } = properties;
      const boost = properties === &apos;*&apos; ? {
        city: 2,
      } : properties.reduce((acc, key, index) =&amp;gt; {
        const boostValue = (length - index) * 2;
        acc[key] = boostValue;
        return acc;
      }, {} as Record&amp;lt;string, number&amp;gt;);

      const result = await searchWithOrama(context.db, {
        term,
        properties,
        boost
      }) as unknown as Results&amp;lt;S&amp;gt;;

      return result;
    },
    [context]
  );

  return {
    isReady: context.isCreated &amp;amp;&amp;amp; context.isIndexed,
    search,
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are some interesting points in this code.&lt;br /&gt;
As you can notice, the search method accepts the terms and a list of properties.&lt;br /&gt;
The first is the search terms that the user wants to search; the second is the list of properties that you want Orama to use during the search (using &lt;code&gt;*&lt;/code&gt; Orama searches in all the properties).&lt;br /&gt;
There is another strange option called boost in this example. This option is a configuration to indicate to Orama the importance of one or more fields in the search.&lt;br /&gt;
The last step is to use this hook in the Search page to run the search.&lt;br /&gt;
In the &lt;code&gt;src/page/Search/index.tsx&lt;/code&gt; this implementation is done in this way.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...
import { useOramaSearch } from &apos;../../core/useOrama/useOramaSearch&apos;;
...

export default function Search() {
  const { isReady, search } = useOramaSearch&amp;lt;typeof CITIES_SCHEMA&amp;gt;();
...

  const onSubmit: FormEventHandler&amp;lt;HTMLFormElement&amp;gt; = useCallback(async (e) =&amp;gt; {
    e.preventDefault();
    const form = e.target as HTMLFormElement;
    const searchTerms = form.elements.namedItem(&apos;searchTerms&apos;) as HTMLInputElement;
    const results = await search(searchTerms.value,
      [searchType]);
    setResults(results)
  }, [search, searchType, setResults])

  ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last info about the search is the search result. It is composed in this way&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;elapsed&lt;/strong&gt; : this object contains the statistic of the search; here, you can find how much time Orama has used to provide the result&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;hits&lt;/strong&gt; : this is the list of the elements that respect the search; by default, Orama returns the first ten elements; you can paginate the result, passing the limit and the offset options in the search method.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;count&lt;/strong&gt; : here; you can find the number of elements that match the terms&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And perfect now the application is ready to search the cities.&lt;/p&gt;
&lt;p&gt;You can test the result &lt;a href=&quot;https://puppo.github.io/orama-search-getting-started/&quot;&gt;in this reference&lt;/a&gt; 🚀&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;As you can notice, integrating Orama into your application is pretty simple.&lt;br /&gt;
The project has born some months ago and obviously it is not perfect and with huge features, but it works well, and the team will release many new features in the further future.&lt;br /&gt;
All the hooks and the context seen in this article could be early replaced by an npm package called &lt;a href=&quot;https://github.com/nearform-oss/use-orama&quot;&gt;use-orama&lt;/a&gt;; it is a working progress 🚧.&lt;/p&gt;
&lt;p&gt;And that&apos;s all! I hope Orama can help your applications search data quickly in the future, and I think it will become a great product in the next few months!&lt;/p&gt;
&lt;p&gt;If you are interested in it, you can learn more about it in the official &lt;a href=&quot;https://docs.oramasearch.com/&quot;&gt;documentation&lt;/a&gt;.&lt;br /&gt;
And don&apos;t forget to follow &lt;a href=&quot;https://twitter.com/OramaSearch&quot;&gt;Orama&lt;/a&gt; on Twitter and &lt;a href=&quot;https://twitter.com/MicheleRivaCode&quot;&gt;Michere Riva&lt;/a&gt; its CTO.&lt;/p&gt;
&lt;p&gt;🚧&lt;br /&gt;
N.b. The project is in beta version at this moment, so breaking changes or some bugs are opportunities to contribute to the project if you want 😎 &lt;a href=&quot;https://github.com/oramasearch/orama&quot;&gt;in the GitHub repository&lt;/a&gt; you can find the GitHub Repo&lt;br /&gt;
🚧&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>orama</category><category>search</category><category>react</category></item><item><title>React Query - useIsFetching &amp; useIsMutation</title><link>https://delpuppo.net/blog/react-query/react-query-useisfetching-useismutation/</link><guid isPermaLink="true">https://delpuppo.net/blog/react-query/react-query-useisfetching-useismutation/</guid><description>Hey folks, Today it is time to talk about two hooks exposed by react query: useIsFetching and...</description><pubDate>Wed, 29 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey folks,&lt;/p&gt;
&lt;p&gt;Today it is time to talk about two hooks exposed by react query: useIsFetching and useIsMutation.&lt;/p&gt;
&lt;p&gt;Each of these hooks could be used to understand if there is a fetching request or if there is a mutation request ongoing in the application.&lt;/p&gt;
&lt;p&gt;They are useful if we need to create a global loader that appears when there are one or more requests on going.&lt;/p&gt;
&lt;p&gt;But how can you use them?&lt;/p&gt;
&lt;p&gt;Let&apos;s start with the useIsFetching.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { useIsFetching } from &apos;@tanstack/react-query&apos;;

export default function Loader() {
  const isFetching = useIsFetching();
  if (!isFetching) return null;

  return &amp;lt;&amp;gt;Fetching...&amp;lt;/&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the syntax is pretty simple. You can import the hook from the library and you can use the hook in your components. The hook returns only a boolean value that indicates if there are one or more fetching requests in the application. Then with this data, you can decide if you have to show a loader or not. Easy peasy!&lt;/p&gt;
&lt;p&gt;Now it&apos;s time to move to the useIsMutation hook. This hook is similar to the previous one, the only different concept is that this hook handles the mutation requests. Let&apos;s see an example!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { useIsMutating } from &apos;@tanstack/react-query&apos;;

export default function Loader() {
  const isMutating = useIsMutating();
  if (!isMutating) return null;

  return &amp;lt;&amp;gt;Mutating...&amp;lt;/&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, the syntax is the same as the previous one, the only difference stands in the name of the hook and in its concept.&lt;/p&gt;
&lt;p&gt;If you want to find more about these two hooks see my Youtube video about them.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://youtu.be/dWuUjDNB6Yc&quot;&gt;https://youtu.be/dWuUjDNB6Yc&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ok, I think you have an idea of how these two hooks work. I hope you enjoyed this content.&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;/p&gt;
&lt;p&gt;Bye Bye 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the code of the video &lt;a href=&quot;https://github.com/Puppo/learning-react-query/tree/03-isfetching-and-mutating&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rahuulmiishra?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Rahul Mishra&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>react</category><category>reactquery</category><category>reacthooks</category></item><item><title>React Query - useMutation</title><link>https://delpuppo.net/blog/react-query/react-query-usemutation/</link><guid isPermaLink="true">https://delpuppo.net/blog/react-query/react-query-usemutation/</guid><description>Hey Folks, It&apos;s time to talk about the second core concept in React Query, mutation. What is...</description><pubDate>Wed, 22 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey Folks,&lt;br /&gt;
It&apos;s time to talk about the second core concept in React Query, mutation.&lt;/p&gt;
&lt;h2&gt;What is it?&lt;/h2&gt;
&lt;p&gt;Mutations are actions that a user can do in your application. You can imagine a mutation as an action to change or create something.&lt;br /&gt;
To understand better in the code what a mutation is, let&apos;s start with a code snippet&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { useMutation } from &apos;@tanstack/react-query&apos;;

const postTodo = async (text: Todo[&apos;text&apos;]): Promise&amp;lt;Todo&amp;gt; =&amp;gt; {
  const response = await fetch(&apos;api/tasks&apos;, {
    method: &apos;POST&apos;,
    headers: {
      &apos;Content-Type&apos;: &apos;application/json&apos;,
    },
    body: JSON.stringify({ text }),
  });
  if (!response.ok) {
    throw new ResponseError(&apos;Failed to insert new todo&apos;, response);
  }
  return await response.json();
};

export const useAddTodo = (): UseAddTodo =&amp;gt; {
  const { mutate: addTodo, isLoading, error } = useMutation(postTodo, {
    onSuccess: () =&amp;gt; {
      // Success actions
    },
    onError: (error) =&amp;gt; {
      // Error actions
    },
  });

  return {
    addTodo,
  };
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the mutation is a simple hook with two params:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The function to handle the request&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The options to handle, in this case, the success and the error hooks, but also to configure the mutation (retry, retry delay and so on).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The result has three main objects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;mutate: this is the action to run the mutation in your code&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;isLoading: this flag indicates if the mutation is ongoing&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;error: this indicates the errors in case there is an error in the request&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using mutations in your React applications, you can handle all those actions to mutate the data and simplify the management of the states of these requests.&lt;/p&gt;
&lt;p&gt;Another important concept to know when you work with mutation is the &lt;a href=&quot;https://tanstack.com/query/v4/docs/react/reference/useQueryClient&quot;&gt;QueryClient&lt;/a&gt;.&lt;br /&gt;
Using the QueryClient, you can invalidate a query already provided and say to react query to ask again for the data because you are sure that those data are not yet valid after the mutation.&lt;br /&gt;
To do that, you have to use the &lt;code&gt;useQueryClient&lt;/code&gt; hook to retrieve the queryClient and using the &lt;code&gt;invalidateQueries&lt;/code&gt; method, you can invalidate the react query cache for a specific query or multiple queries.&lt;br /&gt;
Here you can find an example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { useMutation, useQueryClient } from &apos;@tanstack/react-query&apos;;
import { QUERY_KEY } from &apos;../../../../constants/queryKeys&apos;;

export const useAddTodo = (): UseAddTodo =&amp;gt; {
  const client = useQueryClient();
  const { mutate: addTodo } = useMutation(postTodo, {
    onSuccess: () =&amp;gt; {
      client.invalidateQueries([QUERY_KEY.todos]);
    },
  });
  ...
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok, I think you have an idea of how useMutation and useQueryClient work, but if you want to dive into them, don&apos;t forget to see my Youtube video.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Cpxoxj9sTXA&quot;&gt;https://www.youtube.com/watch?v=Cpxoxj9sTXA&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ok, That&apos;s all!&lt;br /&gt;
I hope you enjoyed this content, and I&apos;ll get back to you soon with another concept of React Query.&lt;/p&gt;
&lt;p&gt;Bye Bye 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the code of the video &lt;a href=&quot;https://github.com/Puppo/learning-react-query/tree/02-mutations&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rahuulmiishra?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Rahul Mishra&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>react</category><category>reactquery</category><category>reacthooks</category></item><item><title>React Query - useQuery</title><link>https://delpuppo.net/blog/react-query/react-query-usequery/</link><guid isPermaLink="true">https://delpuppo.net/blog/react-query/react-query-usequery/</guid><description>Hey Folks, It&apos;s time to take a journey on react query. Don&apos;t you know it? Perfect, you are in the...</description><pubDate>Wed, 15 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey Folks,&lt;br /&gt;
It&apos;s time to take a journey on &lt;a href=&quot;https://tanstack.com/query/latest&quot;&gt;react query&lt;/a&gt;. Don&apos;t you know it? Perfect, you are in the right place 😁&lt;/p&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;What is React Query? React query is an npm library created by &lt;a href=&quot;https://twitter.com/tannerlinsley&quot;&gt;@TannerLinsley&lt;/a&gt;.&lt;br /&gt;
It&apos;s a state manager for react that simplifies many tasks like handling the HTTP request state, saving data in the client to prevent many requests, sharing data in your application using hooks and so on.&lt;br /&gt;
You&apos;ll discover more in this series about it, learn how to use it, and appreciate its simplicity in your react applications.&lt;/p&gt;
&lt;h2&gt;useQuery&lt;/h2&gt;
&lt;p&gt;The first core concept is useQuery. Through it, you can retrieve data from a source and handle all the states of this request in a very simple way.&lt;br /&gt;
Let&apos;s see an example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { useQuery } from &apos;@tanstack/react-query&apos;;

const fetchTodos = async (): Promise&amp;lt;Todo[]&amp;gt; =&amp;gt; {
  const response = await fetch(&apos;api/tasks&apos;);
  if (!response.ok) {
    throw new ResponseError(&apos;Failed to fetch todos&apos;, response);
  }
  return await response.json();
};

export const useTodos = (): UseTodos =&amp;gt; {
  const {
    data: todos = [],
    isLoading,
    isFetching,
    error,
  } = useQuery([&apos;todos&apos;], fetchTodos, {
    refetchOnWindowFocus: false,
    retry: 2,
  });
...
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, you can see the essentials of useQuery.&lt;br /&gt;
UseQuery is a react hook; it takes 3 params:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The query key&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The query function&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The configurations&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&apos;s start with the first one. The query key is a key used by react query to identify your queries; through the key, react query is able to store the result and use it in different parts of the application. The key is used to identify the query, and with it you can also reset the query or change the value by code using the React Query Client.&lt;/p&gt;
&lt;p&gt;The query function is the method used to retrieve data from a source (rest, graphQL, etc. etc.). It&apos;s simple; a function that returns a kind of data could be a simple function or, in most cases, a promise.&lt;/p&gt;
&lt;p&gt;Configurations, ok these are simple :) There are many possible options to run the query in different ways (amount of retries, when refreshing the data, how to cache the data and so on..)&lt;/p&gt;
&lt;p&gt;The result of this hook has three important objects instead&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;data; this object contains the result of your query function. Please, pay attention that the data could be undefined too; this is because on the first call when the request is pending, data is not yet presented&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;isLoading; this flag indicates when react query is loading data. There is also the isFetching flag, which is important if you are creating infinite scrolling. The isFetching flag indicates that there is a request pending, which is perfect if the app is asking for the next info&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;error: this object contains the error if your request has a problem; using it, you can get the error and create a pretty info message for the user&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ok, you have an idea of how useQuery works and what its potentialities are, but if you are more interested in it, you can watch my video to learn more about it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=q2r2yoq5zaQ&quot;&gt;https://www.youtube.com/watch?v=q2r2yoq5zaQ&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;ok, that&apos;s all! I&apos;ll get back to you with another react query feature soon.&lt;/p&gt;
&lt;p&gt;I hope you enjoyed this content.&lt;/p&gt;
&lt;p&gt;Bye Bye 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the code of the video &lt;a href=&quot;https://github.com/Puppo/learning-react-query/tree/01-queries&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Photo by &lt;a href=&quot;https://unsplash.com/@rahuulmiishra?utm_source=Devto&amp;amp;utm_medium=referral&quot;&gt;Rahul Mishra&lt;/a&gt; on &lt;a href=&quot;https://unsplash.com/?utm_source=devto&amp;amp;utm_medium=referral&quot;&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>react</category><category>reactquery</category><category>reacthooks</category></item><item><title>Why I love GitLens in my VsCode - Interactive Rebase</title><link>https://delpuppo.net/blog/gitlens/why-i-love-gitlens-in-my-vscode-interactive-rebase/</link><guid isPermaLink="true">https://delpuppo.net/blog/gitlens/why-i-love-gitlens-in-my-vscode-interactive-rebase/</guid><description>One of the processes I typically do in my daily work is interactive rebase. I commit a lot, and then...</description><pubDate>Tue, 28 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of the processes I typically do in my daily work is interactive rebase.&lt;br /&gt;
I commit a lot, and then before pushing the result, I try to make the history more readable.&lt;/p&gt;
&lt;p&gt;If you have to do that by CLI, you should follow many steps:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; git log --oneline
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command returns the list of the commit&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Now, you have to get the SHA of the commit from where you want to start the interactive rebase and run the command&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; git rebase -i bf2478f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can handle your rebase from your best editor, in my case VsCode.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pick 4fcdf0e add documentation
pick c7a47a9 add documentation

# Rebase bf2478f..c7a47a9 onto bf2478f (2 commands)
#
# Commands:
# p, pick &amp;lt;commit&amp;gt; = use commit
# r, reword &amp;lt;commit&amp;gt; = use commit, but edit the commit message
# e, edit &amp;lt;commit&amp;gt; = use commit, but stop for amending
# s, squash &amp;lt;commit&amp;gt; = use commit, but meld into previous commit
# f, fixup [-C | -c] &amp;lt;commit&amp;gt; = like &quot;squash&quot; but keep only the previous
# commit&apos;s log message, unless -C is used, in which case
# keep only this commit&apos;s message; -c is same as -C but
# opens the editor
# x, exec &amp;lt;command&amp;gt; = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with &apos;git rebase --continue&apos;)
# d, drop &amp;lt;commit&amp;gt; = remove commit
# l, label &amp;lt;label&amp;gt; = label current HEAD with a name
# t, reset &amp;lt;label&amp;gt; = reset HEAD to a label
# m, merge [-C &amp;lt;commit&amp;gt; | -c &amp;lt;commit&amp;gt;] &amp;lt;label&amp;gt; [# &amp;lt;oneline&amp;gt;]
# create a merge commit using the original merge commit&apos;s
# message (or the oneline, if no original merge commit was
# specified); use -c &amp;lt;commit&amp;gt; to reword the commit message
# u, update-ref &amp;lt;ref&amp;gt; = track a placeholder for the &amp;lt;ref&amp;gt; to be updated
# to this position in the new commits. The &amp;lt;ref&amp;gt; is
# updated at the end of the rebase
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When you&apos;ve finished fixing the history, you can save the file, close it and voila, your interactive rebase is completed.&lt;/p&gt;
&lt;p&gt;First, you must know this flow before moving to the next solution.&lt;br /&gt;
The goal of this series is not to forget or don&apos;t learn git, but to help you understand how you can improve your developer experience with git using GitLens.&lt;/p&gt;
&lt;p&gt;So now it&apos;s time to see how the interactive rebase becomes easier with GitLens.&lt;br /&gt;
First, you have to enable the feature from the command palette in this way.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Now you can use it from the commit history. Right-click on the interested commit and choose &quot;Rebase Current Branch onto Commit&quot;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Then you have to choose between two types of rebase, the normal and the interactive. It goes without saying that you have to choose the interactive rebase.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The view that appears is something like this&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Here you can handle the rebase using drag and drop if you want to move the commit, or you can change the action for the commit using a simple dropdown.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;When you&apos;re done, you can click the button in the bottom right, &quot;Start Rebase&quot;, so the rebase will be completed.&lt;/p&gt;
&lt;p&gt;If you change your mind during the rebase, you can abort the operation or close the file or click the &quot;Abort&quot; button.&lt;/p&gt;
&lt;p&gt;But the magic doesn&apos;t end here. When you enable the Interactive Rebase, if you have set up VsCode as the default editor for git, when you run the &lt;code&gt;git rebase -i ....&lt;/code&gt; command from the terminal, by default, VsCode opens the rebase page with the GitLens view.&lt;/p&gt;
&lt;p&gt;Before closing, if you don&apos;t like this feature, you can disable it from the VsCode&apos;s command palette in this way.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Ok, that&apos;s all! I hope now your rebase will be easier and you will have a better developer experience during this operation.&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;/p&gt;
&lt;p&gt;👋 Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you are interested in it, use my referral&lt;/em&gt; &lt;a href=&quot;https://www.gitkraken.com/invite/whbhwrJL&quot;&gt;in this reference&lt;/a&gt; &lt;em&gt;to try GitLens or other GitKraken products for Free!&lt;/em&gt; &lt;a href=&quot;http://gitkraken.com/invite/whbhwrJL&quot;&gt;&lt;strong&gt;&lt;em&gt;gitkraken.com/invite/whbhwrJL&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>git</category><category>vscode</category><category>gitlens</category><category>gitkraken</category></item><item><title>Playwright - Parametrize tests</title><link>https://delpuppo.net/blog/playwright/playwright-parametrize-tests/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-parametrize-tests/</guid><description>Hey folks, Today it&apos;s time to speak about how to parametrize tests with Playwright. There are cases...</description><pubDate>Thu, 23 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey folks,&lt;/p&gt;
&lt;p&gt;Today it&apos;s time to speak about how to parametrize tests with Playwright.&lt;/p&gt;
&lt;p&gt;There are cases where we want to test the same behaviour but with different values, so in these cases, it&apos;s common to create a structure for the test and reuse it with different parameters.&lt;/p&gt;
&lt;p&gt;The easiest way to do that with Playwright is using vanilla javascript.&lt;br /&gt;
You can create an array with different cases, and using the &lt;code&gt;for&lt;/code&gt; clause, you can call the test N times with different parameters.&lt;/p&gt;
&lt;p&gt;Coming back to the Tic Tac Toe application, a real example could be to simulate different rounds and, for each round, indicate the sequence of the moves and who must be the winner.&lt;/p&gt;
&lt;p&gt;An implementation of this scenario can be done in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { expect, test as base } from &quot;@playwright/test&quot;;

const test = base.extend({
  page: async ({ baseURL, page }, use) =&amp;gt; {
    baseURL &amp;amp;&amp;amp; (await page.goto(baseURL));
    await use(page);
  },
});

type TestCase = {
  winner: &quot;X&quot; | &quot;O&quot;;
  moves: number[];
};

const testCases: TestCase[] = [
  {
    winner: &quot;X&quot;,
    moves: [1, 5, 6, 7, 3, 9, 2],
  },
  {
    winner: &quot;O&quot;,
    moves: [3, 1, 5, 7, 9, 4],
  },
];

for (const { winner, moves } of testCases) {
  test(`should win the player &quot;${winner}&quot; with these ${moves}`, async ({
    page,
  }) =&amp;gt; {
    for (const move of moves) {
      await page.locator(`button:nth-child(${move})`).click();
    }

    const winnerParagraph = await page.getByText(/winner/i);
    await expect(winnerParagraph).toContainText(winner);
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, the result is quite simple:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Define a TestCase type&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create an array with the cases&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Iterate the cases and create a &lt;code&gt;test&lt;/code&gt; for each case&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Run and check the test result&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ok, this solution is good and can resolve many of our cases, but you can do more with Playwright!&lt;br /&gt;
It&apos;s possible to load a csv file and use it to map all the test cases. Playwright doesn&apos;t fully expose this solution, but the simplicity with which Playwright is built permits a simple solution to do this.&lt;/p&gt;
&lt;p&gt;Let me show you an example:&lt;/p&gt;
&lt;p&gt;You can map the previous two cases in a csv file like this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// e2e/csv/winners_cases.csv
&quot;test_case&quot;,&quot;winner&quot;,&quot;moves&quot;
&quot;should win the player X&quot;,&quot;X&quot;,&quot;1,5,6,7,3,9,2&quot;
&quot;should win the player O&quot;,&quot;O&quot;,&quot;3,1,5,7,9,4&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then using an npm package called &lt;code&gt;csv-parse&lt;/code&gt; we can load the csv in our test in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { parse } from &quot;csv-parse/sync&quot;;
import fs from &quot;fs&quot;;
import path from &quot;path&quot;;

const cases = parse(
  fs.readFileSync(
    path.join(process.cwd(), &quot;e2e&quot;, &quot;csv&quot;, &quot;winners_cases.csv&quot;)
  ),
  {
    columns: true,
    skip_empty_lines: true,
  }
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now in the &lt;code&gt;records&lt;/code&gt; variable, you have all the data that describe your test cases.&lt;br /&gt;
The last thing to do is to create the tests like in the previous example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; for (const testCase of cases) {
  test(testCase.test_case, async ({ page }) =&amp;gt; {
    const moves = testCase.moves.split(&quot;,&quot;);
    for (const move of moves) {
      await page.locator(`button:nth-child(${move})`).click();
    }

    const winnerParagraph = await page.getByText(/winner/i);
    await expect(winnerParagraph).toContainText(testCase.winner);
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And voila, you have a test suite that runs the test from a csv file.&lt;/p&gt;
&lt;p&gt;In my opinion, both ways are good, but with the csv file you have less control of your code and your tests, and it&apos;s easy to face an error that doesn&apos;t depend on the test or the code but because someone changed the file in the wrong way. So please pay attention to who touches the files 😊&lt;/p&gt;
&lt;p&gt;Ok, I think you have an idea of how you can parameterize your tests.&lt;/p&gt;
&lt;p&gt;It&apos;s time to say goodbye to this series, this is the last article. I&apos;ll come back to you in the future if there will be new features to share with you 😊 But for now, I suppose that&apos;s all!&lt;/p&gt;
&lt;p&gt;I hope you enjoyed it and see you soon!&lt;/p&gt;
&lt;p&gt;test.afterAll(() =&amp;gt; {&lt;/p&gt;
&lt;p&gt;Bye bye 👋&lt;/p&gt;
&lt;p&gt;});&lt;/p&gt;
&lt;p&gt;&lt;em&gt;N.b. you can find the code of this article&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/playwright-series/tree/11-parameterize-test&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>e2e</category></item><item><title>Why I love GitLens in my VsCode - Blame &amp; Compare</title><link>https://delpuppo.net/blog/gitlens/why-i-love-gitlens-in-my-vscode-blame-compare/</link><guid isPermaLink="true">https://delpuppo.net/blog/gitlens/why-i-love-gitlens-in-my-vscode-blame-compare/</guid><description>When you work with git, you want to get info about commits and who changed the codebase...</description><pubDate>Tue, 21 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When you work with git, you want to get info about commits and who changed the codebase quickly.&lt;/p&gt;
&lt;p&gt;With GitLens, you can get much info about your current file without losing focus on it. First, at the top of your file, you can get info about the last change and the name of the person who pushed that commit. In addition, there is also info on the number of people that touched the file.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;This information is clickable. You can click on the part relative to the last commit or the other one.&lt;br /&gt;
The first part opens the VsCode command with some possible actions to see the commit; you can see all the files relative to the commit, open the commit detail, and see the commit in the commit-graph. This is very helpful if you want to get info quickly about the changes in the file.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Instead, If you click on the second part (that is relative to the other authors of the file), GitLens opens a new bar on the left of the file and shows, for each line, the last commit relative to it, so you can understand who and why someone has changed the line.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;This view is also available using the icon with the git logo in the top right of the file, and you can toggle this view by clicking it easily.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;All these features are fantastic, but sometimes we need more, for instance, searching for a commit or comparing two different commits.&lt;br /&gt;
To do that, in the GitLens bar, you can find an option called &quot;Search &amp;amp; Compare&quot;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s start with the search feature. Using this feature, you can search for a commit by different filters: commit message, author, SHA, file or changes. Typically, in my case, I use this feature to find an old commit by message or by author. The feature is very straightforward. If you click the button, the extension opens a command with different options; you can select your choice and type your terms. After that, in the GitLens panel will appear the results of the search.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;With this view, you can check the commits and see the files changed in those commits.&lt;/p&gt;
&lt;p&gt;After the search could be necessary to compare two commits, you can use the other button called &quot;Compare references&quot; to do that.&lt;br /&gt;
Also, this feature is easy to use. Clicking the button &quot;Compare References&quot; appears a new VsCode command, where you can type the reference of your branches/tags or commits. Obviously, you have to indicate two references for the comparison.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;For me, this is really convenient when I have to compare two different versions of the code in the past or to check when and why a piece of code has changed.&lt;/p&gt;
&lt;p&gt;Ok, that&apos;s all folk.&lt;br /&gt;
I hope you have other tips for improving your productivity with git using GitLens.&lt;/p&gt;
&lt;p&gt;Let me know if you think these features could be helpful to you too or if you already use them in your daily work.&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;/p&gt;
&lt;p&gt;Bye bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you are interested in it, use my referral&lt;/em&gt; &lt;a href=&quot;https://www.gitkraken.com/invite/whbhwrJL&quot;&gt;in this reference&lt;/a&gt; &lt;em&gt;to try GitLens or other GitKraken products for Free!&lt;/em&gt; &lt;a href=&quot;http://gitkraken.com/invite/whbhwrJL&quot;&gt;&lt;strong&gt;&lt;em&gt;gitkraken.com/invite/whbhwrJL&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>git</category><category>vscode</category><category>gitlens</category><category>gitkraken</category></item><item><title>Playwright - Not just for Frontend</title><link>https://delpuppo.net/blog/playwright/playwright-not-just-for-frontend/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-not-just-for-frontend/</guid><description>In this path with Playwright we spent a lot of time speaking about e2e tests and component testing in...</description><pubDate>Thu, 16 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In this path with Playwright we spent a lot of time speaking about e2e tests and component testing in the frontend world. But now its time to spill the beans and tell you a secret. Playwright can be used on the backend side too.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;API Testing&lt;/h2&gt;
&lt;p&gt;Playwright can test REST API too. In some scenarios, you don&apos;t have a UI, but you have an API integration and have to test your integration in some way.&lt;br /&gt;
Using API testing with Playwright, you can call your APIs without a user interface and check their correct execution.&lt;/p&gt;
&lt;p&gt;The key volta for doing that on Playwright is the &lt;code&gt;request&lt;/code&gt; object. Using this object, you can call your APIs and check their result.&lt;/p&gt;
&lt;p&gt;But let&apos;s take a look at it.&lt;/p&gt;
&lt;p&gt;First, I didn&apos;t create a backend API for this example, but I used a fake API to test. I created it with json-server and json-server-auth. They are two npm packages that use a JSON file as a database and expose the database in an API. You can find more about json-server in its &lt;a href=&quot;https://github.com/typicode/json-server&quot;&gt;documentation&lt;/a&gt; and about json-server-auth &lt;a href=&quot;https://www.npmjs.com/package/json-server-auth&quot;&gt;in this reference&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It&apos;s time to understand how API testing works.&lt;br /&gt;
A straightforward example could be this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test(&quot;should call a winner&quot;, async ({ request }) =&amp;gt; {
  const result = await request.post(&quot;http://localhost:3001/api/winners&quot;, {
    data: {
      winner: &quot;O&quot;,
    },
  });
  expect(result.ok()).toBeTruthy();
  expect(await result.json()).toEqual(
    expect.objectContaining({
      winner: &quot;O&quot;,
      id: expect.any(Number),
    })
  );
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This example is to understand the structure of an API test, then you&apos;ll see a more complex example.&lt;br /&gt;
The &lt;code&gt;request&lt;/code&gt; object is exposed by Playwright in each test, like the page object in a standard e2e test in the browser. With this object, you can call one or more HTTP requests. Then, when you have the result of the requests, you can check if the result is ok or if the response respects a specific schema.&lt;br /&gt;
As you can notice, it&apos;s elementary&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;create a request&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;wait for the result&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;check the result&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Typically, a simple API test has this flow, probably before you could have a login request because your APIs are under authentication, but a login request is just another request before.&lt;/p&gt;
&lt;p&gt;I created a more complex example to give you a better idea of the flow you can create with Playwright and API testing (This approach could be used with e2e tests too).&lt;/p&gt;
&lt;p&gt;The example is so structured. For each test, the suite:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;creates a new json-server database&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;creates a new json-server process&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;runs the tests&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;kill the json-server&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;delete the temporary database&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&apos;s start from the beginning. I created two files for the tests. One file is the database with one row for the winners and one user inside. The other file is the route file to make a sort of authentication in the API. (you can learn more about that following the json-server documentation seen before).&lt;/p&gt;
&lt;p&gt;So these two files are in the db folder and appear in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// db_test.json
{
  &quot;users&quot;: [
    {
      &quot;email&quot;: &quot;test@test.it&quot;,
      &quot;password&quot;: &quot;$2a$10$ONSI/ac5n4iyMj7LfcRIsOzYQ8dqPYK33TTH1Qp7YORPjvofkoTgS&quot;,
      &quot;id&quot;: 1
    }
  ],
  &quot;winners&quot;: [
    {
      &quot;winner&quot;: &quot;X&quot;,
      &quot;createdAt&quot;: &quot;2023-01-16T21:06:20.749Z&quot;,
      &quot;id&quot;: 1
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// routes_test.json
{
  &quot;/api/*&quot;: &quot;/$1&quot;,
  &quot;users&quot;: 600,
  &quot;winners&quot;: 664
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now it&apos;s time to create a routine for each test that gets these two files, creates a copy of the database, and runs the json-server in a specific port. In this way, if we have many tests in parallel, each test doesn&apos;t depend on the actions done in the other tests.&lt;/p&gt;
&lt;p&gt;To do that, I created this code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// api.spec.ts
import { expect, test } from &quot;@playwright/test&quot;;
import { ChildProcess, exec } from &quot;child_process&quot;;
import { randomUUID } from &quot;crypto&quot;;
import { copyFile, unlink } from &quot;fs/promises&quot;;
import { join } from &quot;path&quot;;

const dbName = `db_test_${randomUUID()}.json`;

const dbInitPath = join(process.cwd(), &quot;db&quot;, &quot;db_test.json&quot;);
const dbPath = join(process.cwd(), &quot;db&quot;, dbName);

const portsMapping = {
  chromium: 3001,
  firefox: 3002,
  webkit: 3003,
} as const;
let port: 3001 | 3002 | 3003;
let baseUrl: string;
let api_process: ChildProcess;

test.beforeAll(async ({ browserName }) =&amp;gt; {
  port = portsMapping[browserName];
  baseUrl = `http://localhost:${port}/api`;
  // Create a file to be uploaded
  await copyFile(dbInitPath, dbPath);

  // Start the server
  await new Promise&amp;lt;void&amp;gt;((resolve, reject) =&amp;gt; {
    api_process = exec(
      `npx json-server-auth --watch ${dbPath} --port ${port} --routes db/routes_test.json`,
      err =&amp;gt; {
        if (err) reject(err);
      }
    );

    api_process.stdout?.on(&quot;data&quot;, data =&amp;gt; {
      if (data.includes(&quot;Watching...&quot;)) {
        setTimeout(() =&amp;gt; {
          resolve();
        }, 10);
      }
    });
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are some critical points in this code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const dbName = `db_test_${randomUUID()}.json`;

const dbInitPath = join(process.cwd(), &quot;db&quot;, &quot;db_test.json&quot;);
const dbPath = join(process.cwd(), &quot;db&quot;, dbName);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here I created two new variables, one contains the path of the init database file, and the second one is the path for the database used by the test.&lt;/p&gt;
&lt;p&gt;Then I mapped each browser in different ports, so if the tests run in parallel, there aren&apos;t problems of concurrency in the same database. (If your suite is only for API testing you can run the suite only with one browser, in this case, I kept the suite like in the previous articles)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const portsMapping = {
  chromium: 3001,
  firefox: 3002,
  webkit: 3003,
} as const;
let port: 3001 | 3002 | 3003;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the beforeAll hook, I created the copy of the database, and then I ran the json-server process to expose the API.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test.beforeAll(async ({ browserName }) =&amp;gt; {
  port = portsMapping[browserName];
  baseUrl = `http://localhost:${port}/api`;
  // Create a file to be uploaded
  await copyFile(dbInitPath, dbPath);

  // Start the server
  await new Promise&amp;lt;void&amp;gt;((resolve, reject) =&amp;gt; {
    api_process = exec(
      `npx json-server-auth --watch ${dbPath} --port ${port} --routes db/routes_test.json`,
      err =&amp;gt; {
        if (err) reject(err);
      }
    );

    api_process.stdout?.on(&quot;data&quot;, data =&amp;gt; {
      if (data.includes(&quot;Watching...&quot;)) {
        setTimeout(() =&amp;gt; {
          resolve();
        }, 10);
      }
    });
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It seems a bit strange, but as you can see, in this way, I simulated a new database for each test file, so each test has its database and doesn&apos;t depend on the other tests.&lt;/p&gt;
&lt;p&gt;As you can imagine, in this way, you can create a clean environment for each test.&lt;/p&gt;
&lt;p&gt;Then I added another hook, the afterAll, where I killed the API process and deleted the database file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test.afterAll(async () =&amp;gt; {
  console.log(&quot;Kill server&quot;, baseUrl);
  api_process.kill();
  await unlink(dbPath);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then I created the first test that checks if the result of the get method returns an array of winners.&lt;br /&gt;
This is easy peasy&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test(&quot;should return an array of winner&quot;, async ({ request }) =&amp;gt; {
  const result = await request.get(`${baseUrl}/winners`);
  expect(result.ok()).toBeTruthy();
  expect(await result.json()).toEqual(
    expect.arrayContaining([
      expect.objectContaining({
        winner: expect.stringMatching(/^O|X$/),
        id: expect.any(Number),
      }),
    ])
  );
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I can call the API and get the result using the request object, and then I can check if the result is ok and if the response is like expected.&lt;br /&gt;
This example is pretty simple, so I don&apos;t want to spend too much time on it; I guess it is comprehensible.&lt;br /&gt;
But now it&apos;s time to move to another example that is a bit more complex.&lt;br /&gt;
The test has to test the insert in the winners&apos; collection. To do this action, the user must be logged in, so before doing the post, we have to login into the API. The result is something like this.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test(&quot;should insert a winner&quot;, async ({ request }) =&amp;gt; {
  console.log(&quot;Testing the server&quot;, baseUrl);
  const loginResult = await request.post(`${baseUrl}/login`, {
    data: {
      email: &quot;test@test.it&quot;,
      password: &quot;test&quot;,
    },
  });
  expect(loginResult.ok()).toBeTruthy();
  const { accessToken } = await loginResult.json();
  const result = await request.post(`${baseUrl}/winners`, {
    data: {
      winner: &quot;O&quot;,
    },
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
  });
  expect(result.ok()).toBeTruthy();
  expect(await result.json()).toEqual(
    expect.objectContaining({
      winner: &quot;O&quot;,
      id: expect.any(Number),
    })
  );
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, in this example, I created a flow of authentication, and then the test moves to the post request for the winners if it is ok. Yes, probably if you are familiar with testing; this is not rocket science, but you can see how it&apos;s easy to create API testing with Playwright.&lt;/p&gt;
&lt;p&gt;So far so good; in this article, you discovered API testing with Playwright and a medium example of how you can create a flow of API testing with Playwright.&lt;/p&gt;
&lt;p&gt;That&apos;s all folks!&lt;br /&gt;
I hope you enjoyed it and see you soon!&lt;/p&gt;
&lt;p&gt;Bye bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;N.B. you can find the code of this article&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/playwright-series/tree/10-api-testing&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>apitesting</category></item><item><title>Why I love GitLens in my VsCode - First Steps</title><link>https://delpuppo.net/blog/gitlens/why-i-love-gitlens-in-my-vscode-first-steps/</link><guid isPermaLink="true">https://delpuppo.net/blog/gitlens/why-i-love-gitlens-in-my-vscode-first-steps/</guid><description>In my daily routine, I work with git, and I suppose it&apos;s the same for you. I know all the standard...</description><pubDate>Tue, 14 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In my daily routine, I work with git, and I suppose it&apos;s the same for you.&lt;br /&gt;
I know all the standard commands to work with it in my terminal, and I love them.&lt;br /&gt;
I think every developer must know git and its commands, and work with it by the command line. If you don&apos;t know at least the basic git commands, please go to study them right away. There are many articles or videos about them and don&apos;t forget the documentation; that is the best place to learn and study new things.&lt;br /&gt;
When you have the fundaments, if you want to dive into it, this book is for &lt;a href=&quot;https://git-scm.com/book/it/v2&quot;&gt;you&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Btw, today I want to speak about something different, I love git and I love terminal, but sometimes I love having the info visualised appealingly and get info about the source control quickly. I work with VsCode typically, so some months ago I tried to find a solution for this editor that resolves what was said before. After googling and some testing, the result of my search was: &lt;a href=&quot;https://gitlens.amod.io/&quot;&gt;GitLens&lt;/a&gt;.&lt;br /&gt;
Now, I want to show you how it works and how it can improve your routine.&lt;br /&gt;
So don&apos;t waste time and let&apos;s jump in it!&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;First of all, to use GitLens you have to install it. This process is a piece of cake if you are familiar with VsCode.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Open your editor&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to the extension tab&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Search &quot;gitlens&quot;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install the extension&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;N.B. There are two extensions, the official and the insider; you can choose the one you prefer because the insider it&apos;s typically stable too. It goes without saying the insider version could have some bugs sometimes.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;First Impact&lt;/h2&gt;
&lt;p&gt;After the installation, the extension is ready to use, and you can find it in your sidebar.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Before going on, I want to say you that the extension is free, but not all the features are free. Some cool features are available only in the pro subscription; you can find more &lt;a href=&quot;https://help.gitkraken.com/gitlens/gitlens-plus/&quot;&gt;in this reference&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As you can notice from the previous image, GitLens has different sections, and each section has its goal. Each title is already comprehensible as you can see, but now we&apos;ll deep into some of them and not only.&lt;/p&gt;
&lt;p&gt;I&apos;ll use the &lt;a href=&quot;https://github.com/LyraSearch/lyra&quot;&gt;Lyra&lt;/a&gt; repository for this article, so thanks to the &lt;a href=&quot;https://docs.lyrasearch.io/&quot;&gt;Lyra&lt;/a&gt; contributors if this article has a great git history and awesome code.&lt;/p&gt;
&lt;h2&gt;Repository&lt;/h2&gt;
&lt;p&gt;In this tab, you can find all the info about your repository: branches, commits, tags, contributors and so on. I use this section sparingly because, in other areas, I find these data based on my needs. But here, you can find the best overview of your repository.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Commits&lt;/h2&gt;
&lt;p&gt;This section starts to become more interesting. Here there is the commits list of the current branch.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Typically, I don&apos;t use this section to see the commit; I have a git alias showing me the terminal&apos;s history. But, in this section, there are 4 commands very helpful:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Undo the commit (please pay attention when you use it)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Compare the commit with the head&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy the SHA&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Open the commit in the browser&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The first, the second, and the last one are my favourites because I always forget the undo syntax, comparing the commit in some cases is very helpful using this tool, and opening the commit in the browser is straightforward in this way.&lt;br /&gt;
Another cool feature presented in this section is the commit-graph. This is a pro feature, but it&apos;s very powerful to understand the status of the branches. You can find it in the title bar of the Commit section.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The result of this command is this&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;With this graph understanding the branches&apos; status or filtering or searching in your repository is easy, and you can find your answer quickly.&lt;br /&gt;
This is very helpful for me when I want to check where my current branch is compared to the main branch or others.&lt;/p&gt;
&lt;h2&gt;File history and line history&lt;/h2&gt;
&lt;p&gt;These sections are incredible! If you have a file open in the editor in these two tabs, you can see the history of the file in your repository and the history of the line where your cursor is.&lt;br /&gt;
Another cool integration are the notions present on the right of the current line directly in the file, where you can find the last commit&apos;s info of that line of code. So you can blame your colleague 🤪&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The last feature that I want to face out in this article is the button that permits to see the changes between the current version of the file and the previous one. This button is in the top right of the file and the result if you click it is like this.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;This feature is very cool and allow us to see immediately what has changed in the last commit. In this view, it&apos;s possible to continue the history navigation using the same icon at the top right of the button.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;So far so good; I suppose that as a first look at GitLens, that&apos;s all. In the next article, we&apos;ll dive into other cool features in GitLens, but for now, let me know what you think about it. Do you already use it? Which are your impressions in this case?&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;/p&gt;
&lt;p&gt;Bye bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you are interested in it, use my referral&lt;/em&gt; &lt;a href=&quot;https://www.gitkraken.com/invite/whbhwrJL&quot;&gt;in this reference&lt;/a&gt; &lt;em&gt;to try GitLens or other GitKraken products for Free!&lt;/em&gt; &lt;a href=&quot;https://www.gitkraken.com/invite/whbhwrJL&quot;&gt;&lt;em&gt;https://www.gitkraken.com/invite/whbhwrJL&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>git</category><category>vscode</category><category>gitlens</category><category>gitkraken</category></item><item><title>Playwright - Parallelism and sharding</title><link>https://delpuppo.net/blog/playwright/playwright-parallelism-and-sharding/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-parallelism-and-sharding/</guid><description>Hey Folks, Today I&apos;ll speak about parallelism and sharding with Playwright, so don&apos;t waste time and...</description><pubDate>Thu, 09 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey Folks,&lt;/p&gt;
&lt;p&gt;Today I&apos;ll speak about parallelism and sharding with Playwright, so don&apos;t waste time and jump into it.&lt;/p&gt;
&lt;p&gt;By default, Playwright runs your tests in parallel. It uses many worker processes at the same time. But you have different solutions to handle or remove parallelism in Playwright.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Test files are in parallel, and each file is executed in order, from the first test to the last one. This is the default configuration&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Using &lt;code&gt;test.describe.configure&lt;/code&gt; you can configure a file to run its tests in parallel&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;it&apos;s possible to configure the entire project to have all tests in all files that run in parallel using testProject.fullyParallel or testConfig.fullyParallel&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;it&apos;s possible to disable the parallelism limit by setting the number of workers to one.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Worker processes&lt;/h2&gt;
&lt;p&gt;Each test runs in its own worker processes, and communication between workers is impossible. A process is an Os process that runs independently and is orchestrated by the test runner. Each worker has the same environment and starts its own browser.&lt;br /&gt;
Playwright Test reuses a single worker as much as possible to make testing faster, so multiple test files are usually run in one worker one after another.&lt;br /&gt;
Each time a test fails, the worker is shouted down to guarantee a pristine environment for the following tests.&lt;/p&gt;
&lt;h3&gt;Limit the worker processes&lt;/h3&gt;
&lt;p&gt;Nonetheless, you can control the maximum number of parallel worker processes via the command line or in the configuration file in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx playwright test --workers 4
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// playwright.config.ts
import { defineConfig } from &apos;@playwright/test&apos;;

export default defineConfig({
  // Limit the number of workers on CI, use default locally
  workers: process.env.CI ? 2 : undefined,
});

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Disable parallelism&lt;/h2&gt;
&lt;p&gt;However, it&apos;s possible to disable the parallelism too. To do that, the solution is to set the workers&apos; configuration to one by command line or configuration file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx playwright test --workers 1
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// playwright.config.ts
import { defineConfig } from &apos;@playwright/test&apos;;

export default defineConfig({
  // Limit the number of workers on CI, use default locally
  workers: 1,
});

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Parallelize tests in a single file&lt;/h2&gt;
&lt;p&gt;Playwright, by default, runs all the tests in a single file in order, but it&apos;s possible to run them in parallel too. To do that, you have two possible solutions, by the configuration file or by the &lt;code&gt;test.describe.configure()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The solution by the configuration file enables parallelism in each file of your test suite instead the &lt;code&gt;test.describe.configure()&lt;/code&gt; enables it just in a single file.&lt;/p&gt;
&lt;p&gt;By the way, the setting of this configuration is elementary; if you decide to enable it by the config file, the solution is this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// playwright.config.ts
import { defineConfig } from &apos;@playwright/test&apos;;

export default defineConfig({
  fullyParallel: true,
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;else, if you want to enable parallelism using &lt;code&gt;test.describe.configure()&lt;/code&gt; the solution is this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { test } from &apos;@playwright/test&apos;;

test.describe.configure({ mode: &apos;parallel&apos; });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&apos;s essential to spend some words about &lt;code&gt;beforeAll&lt;/code&gt; and &lt;code&gt;afterAll&lt;/code&gt; hook. In this case, these hooks will be executed for each process, so they become like &lt;code&gt;beforeEach&lt;/code&gt; and &lt;code&gt;afterEach&lt;/code&gt; hooks.&lt;/p&gt;
&lt;h2&gt;Serial mode&lt;/h2&gt;
&lt;p&gt;Sometimes, you have to run the tests in the same file in serial. To do that in Playwright, you can configure the serial mode. In this way, Playwright executes all the tests in sequence, but if one of the chain fails, the following tests will not execute, and so they will be skipped.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This kind of configuration exists in Playwright, but it&apos;s not recommended.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;However, if you want to enable it, you have to add this line of code to your test file&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { test, Page } from &apos;@playwright/test&apos;;

// Annotate entire file as serial.
test.describe.configure({ mode: &apos;serial&apos; });
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Shard tests between multiple machines&lt;/h2&gt;
&lt;p&gt;Another cool feature, if you want to speed up your test suite, is the shard configuration. This configuration permits splitting the execution of the test suite in different machines so that you can parallelise your suite much more. This configuration helps the execution of your CI, so you don&apos;t have to waste too much time waiting for the CI.&lt;br /&gt;
To use this configuration, you have to use the &lt;code&gt;--shard&lt;/code&gt; option and indicate 2 numbers&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;the total of shards&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;which shard Playwright has to run&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, for instance, an example could be like this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx playwright test --shard=1/3
npx playwright test --shard=2/3
npx playwright test --shard=3/3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this way, you are dividing your test suite into 3 shards, and each command runs one of them.&lt;/p&gt;
&lt;h2&gt;Control test order&lt;/h2&gt;
&lt;p&gt;By default, Playwright runs all the tests in parallel, so it doesn&apos;t guarantee the order execution. However, if you disable the parallelism, you should need to execute the test in a specific order. To do that, you have two options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Sort test files alphabetically&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use a &quot;test list&quot; file&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can imagine, for the first option, you have to choose a rule to order your files; for instance, in the official documentation, they say to add a prefix with three numbers: 001, 002, 003, etc. etc., easy peasy lemon squeeze.&lt;/p&gt;
&lt;p&gt;For the second option instead, the game becomes trickier. You have to put your test in a helper file, and then you have to create a new file that imports all the helpers, and you have to wrap each helper in a &lt;code&gt;test.describe&lt;/code&gt;.&lt;br /&gt;
Then, you have to disable the parallelism and indicate to Playwright to use only the file that contains the helpers. In my opinion, yes, it&apos;s a solution, but probably, I prefer the first approach. To leave you a concrete idea, here you can find a possible implementation picked directly from the official documentation&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// feature-a.spec.ts
import { test, expect } from &apos;@playwright/test&apos;;

export default function createTests() {
  test(&apos;feature-a example test&apos;, async ({ page }) =&amp;gt; {
    // ... test goes here
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// feature-b.spec.ts
import { test, expect } from &apos;@playwright/test&apos;;

export default function createTests() {
  test.use({ viewport: { width: 500, height: 500 } });

  test(&apos;feature-b example test&apos;, async ({ page }) =&amp;gt; {
    // ... test goes here
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// test.list.ts
import { test } from &apos;@playwright/test&apos;;
import featureBTests from &apos;./feature-b.spec.ts&apos;;
import featureATests from &apos;./feature-a.spec.ts&apos;;

test.describe(featureBTests);
test.describe(featureATests);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// playwright.config.ts
import { defineConfig } from &apos;@playwright/test&apos;;

export default defineConfig({
  workers: 1,
  testMatch: &apos;test.list.ts&apos;,
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another critical thing to remember in this solution is to wrap all the tests in the helpers with a function; in this way, your tests will not depend on the import/export statement, and you will prevent strange mistakes.&lt;/p&gt;
&lt;p&gt;Ok, that&apos;s all! Now, I suppose you have an idea of how parallelism works in Playwright and have all the notions to handle it.&lt;/p&gt;
&lt;p&gt;I hope you enjoyed this article, and if you have any questions, don&apos;t hesitate to reach out to me, you are welcome.&lt;/p&gt;
&lt;p&gt;See you soon folks&lt;br /&gt;
Bye Bye 👋&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>e2e</category></item><item><title>Playwright - Visual Comparisons</title><link>https://delpuppo.net/blog/playwright/playwright-visual-comparisons/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-visual-comparisons/</guid><description>Hi there, Today I want to speak about Visual comparisons with Playwright. In some projects is...</description><pubDate>Thu, 02 Feb 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi there,&lt;/p&gt;
&lt;p&gt;Today I want to speak about &lt;strong&gt;Visual comparisons&lt;/strong&gt; with Playwright.&lt;/p&gt;
&lt;p&gt;In some projects is crucial to respect the same size for the component on the page, or to guarantee the exact visualization each time, or to ensure the same colour, etc.&lt;/p&gt;
&lt;p&gt;Playwright exposes this feature out of the box. To do that, Playwright uses snapshots and compares a specific snapshot with the test result to check that nothing has changed.&lt;/p&gt;
&lt;p&gt;But don&apos;t waste time, and let&apos;s see how it works.&lt;/p&gt;
&lt;p&gt;I want to use the Square component for this example, but you have to refactor it before moving to the test. First, you have to move the X and O png images from the public folder to the Square component folder. After that, you have to refactor the component so that it imports these images and uses them to render the icon.The result is something like this:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Folder Structure&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; Square
    O.png
    Square.module.scss
    Square.tsx
    X.png
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Square Component&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { TicTacToeValue } from &apos;../../models/TicTacToeValue&apos;;
import { Nullable } from &apos;../../utils/Nullable&apos;;
import Icon from &apos;../Icon/Icon&apos;;
import OIcon from &apos;./O.png&apos;;
import styles from &apos;./Square.module.scss&apos;;
import XIcon from &apos;./X.png&apos;;

interface SquareProps {
  value: Nullable&amp;lt;TicTacToeValue&amp;gt;;
  onSelect: () =&amp;gt; void
}

export default function Square(
  { value, onSelect }: SquareProps
) {

  const icon = value === &apos;X&apos; ? XIcon : OIcon;

  return (
    &amp;lt;button
      type=&apos;button&apos;
      className={styles.Square}
      onClick={onSelect}&amp;gt;
      {value &amp;amp;&amp;amp; &amp;lt;Icon src={icon} title={value} /&amp;gt;}
    &amp;lt;/button&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perfect, now you are ready to create your first test to check the visual comparisons.&lt;/p&gt;
&lt;p&gt;Before moving on to code, you should meet what you have to know to make visual comparisons with Playwright, and the only thing that you have to know is the assertion &lt;code&gt;toHaveScreenshot&lt;/code&gt;. This assertion is your best friend if you want to implement visual comparisons with Playwright, it has some configurations, but you will see the most commons later. Now, don&apos;t waste and get your hands dirty.&lt;/p&gt;
&lt;p&gt;First of all, you have to create a new file called &lt;code&gt;src/components/Square/Square.spec.tsx&lt;/code&gt;, that will contain your tests. As first example, you can create a new test that checks if the Square component shows the X icon if the value is &lt;code&gt;X&lt;/code&gt;. To do that, you have to make a test like this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { expect, test } from &apos;@playwright/experimental-ct-react&apos;;
import Square from &apos;./Square&apos;;

test.describe(&apos;Square&apos;, () =&amp;gt; {
  test(&apos;should show the X icon without regression&apos;, async ({ mount, page }) =&amp;gt; {
    await mount(&amp;lt;Square value={&apos;X&apos;} onSelect={() =&amp;gt; { }} /&amp;gt;);
    await expect(page).toHaveScreenshot();
  });
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, this article shows the visual comparisons in the testing of the components, but you can use it in the e2e tests too.Ok, now it&apos;s time to see the result by running the command &lt;code&gt;npm run test-ct&lt;/code&gt;.The result is not like expected, I suppose. In fact, the result shows an error like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Error: A snapshot doesn&apos;t exist at playwright-series/snapshots/components/Square/Square.spec.tsx-snapshots/Square-should-show-the-X-icon-without-regression-1-chromium-darwin.png, writing actual.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can imagine, Playwright tries to run your tests but doesn&apos;t find a snapshot to compare with your result, so it raises an error for each platform (Chrome, Firefox and WebKit). However, you can notice that three new files came up in your project. These files are the snapshot of your test. You can find them at the root of your project in the folder &lt;code&gt;__snapshots__&lt;/code&gt; &lt;strong&gt;.&lt;/strong&gt; From here, Playwright can run your test and check if the result is like on these snapshots. To check that, you can rerun the previous command and notice that the result will be better and your tests will be passed.&lt;/p&gt;
&lt;p&gt;To double-check if the visual comparison works, you can change the icon sizes in the &lt;code&gt;Square.module.scss&lt;/code&gt; file. For instance, from 100x100 pixels to 101x101 pixels.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.Square {
  width: 101px;
  height: 101px;
  background-color: #fff;
  border: 1px solid #000;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  font-weight: bold;
  cursor: pointer;
  transition: background-color 0.3s ease;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you rerun the command &lt;code&gt;npm run test-ct&lt;/code&gt;, the result shows something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;3 failed
    [chromium] components/Square/Square.spec.tsx:6:3 Square should show the X icon without regression
    [firefox] components/Square/Square.spec.tsx:6:3 Square should show the X icon without regression
    [webkit] components/Square/Square.spec.tsx:6:3 Square should show the X icon without regression
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And as you can imagine, your test suite failed because the result is not exactly like expected.&lt;/p&gt;
&lt;p&gt;When we run with visual comparison, as you can imagine, introducing a regression is very easy, a pixel of difference and boom, the suite fails. Playwright knows this problem and permits you to be less strict in these cases. It&apos;s important to remember that by default, Playwright is strict and checks every single pixel of difference, but you can configure it with a threshold. The most commons are maxDiffPixelRatio, maxDiffPixels or threshold.Each configuration permits you to be slackers in different cases. For instance, if you choose the maxDiffPixels configuration, you can write the previous test in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test(&apos;should show the X icon without regression&apos;, async ({ mount, page }) =&amp;gt; {
  await mount(&amp;lt;Square value={&apos;X&apos;} onSelect={() =&amp;gt; { }} /&amp;gt;);
  await expect(page).toHaveScreenshot({ maxDiffPixels: 500 });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you run the command &lt;code&gt;npm run test-ct&lt;/code&gt; , now the test suite has passed, and as you can imagine, Playwright has tested your new snapshot using the maxDiffPixels configuration. Hence, even if the size is different, the result is ok because it respects the maxDiffPixels configuration.&lt;/p&gt;
&lt;p&gt;These kinds of configurations could be set as default if you want. For instance, you can decide that all the visual comparison tests must have the maxDiffPixels of 500. To do that, you can configure Playwright to have this configuration by default. In the Playwright configuration file, you can set the expect method with this configuration:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineConfig } from &apos;@playwright/test&apos;;
export default defineConfig({
  expect: {
    toHaveScreenshot: { maxDiffPixels: 500 },
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Last but not least, sometimes changing the component structure is required. In these cases, you have to change snapshots so that Playwright has the new comparison images in the future to check the results. To do that, you can run your test with the option &lt;code&gt;--update-snapshots&lt;/code&gt;. This indicates to Playwright that the snapshots are old and that it has to change the previous results with the new ones.&lt;/p&gt;
&lt;p&gt;Ok, I suppose you have a good idea of how visual comparison works on Playwright, and you can start to play with it without problems.I think that&apos;s all from Visual Comparison, I hope you enjoyed this content and if you have any questions, you are welcome!&lt;/p&gt;
&lt;p&gt;See you soon folk&lt;/p&gt;
&lt;p&gt;Bye bye&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the source code of this article&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/playwright-series/tree/09-visual-comparisons&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>e2e</category><category>visual</category></item><item><title>Playwright - Mock API</title><link>https://delpuppo.net/blog/playwright/playwright-mock-api/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-mock-api/</guid><description>Hi there, Today I want to talk about how to mock API with Playwright. To do that, I add a new...</description><pubDate>Thu, 26 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi there,&lt;br /&gt;
Today I want to talk about how to mock API with Playwright.&lt;/p&gt;
&lt;p&gt;To do that, I add a new feature to the usual example. When one of the players wins, the system sends a POST request to the URL &lt;code&gt;http://localhost:3001/api/winners&lt;/code&gt; to save the history of the results of the games.&lt;/p&gt;
&lt;p&gt;The API server is built using &lt;a href=&quot;https://github.com/typicode/json-server&quot;&gt;json-server&lt;/a&gt;. You can find all the steps to reproduce the feature in this &lt;a href=&quot;https://github.com/Puppo/playwright-series/commit/55467d588c7017bb1c8b851ba17b38fe9faa070c&quot;&gt;commit&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Mock API&lt;/h2&gt;
&lt;p&gt;Mocking API is a common feature in testing frameworks. In Playwright, to do that, you have to use the &lt;code&gt;page.route&lt;/code&gt; method. This method permits you to work with API in different ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Mocking responses&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Modify requests&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Modify responses&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Abort requests&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Any request that a page does, including XHRs and fetch requests, can be tracked, modified and mocked in Playwright using &lt;code&gt;page.route&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Mock API in action&lt;/h2&gt;
&lt;p&gt;In this article, I want to show you how to start to use this API.&lt;br /&gt;
Let&apos;s start with the test. The test is straightforward; it reproduces a game where the Player &lt;code&gt;X&lt;/code&gt; wins and, in the end, checks if the application fetches the POST request to save the winner.&lt;/p&gt;
&lt;p&gt;The test&apos;s base is composed in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test(&quot;should register the winner calling the winner API[POST]&quot;, async ({
  page,
  playerXWinMoves,
}) =&amp;gt; {
  /// mock the API
  for (const move of playerXWinMoves) {
    await page.locator(`button:nth-child(${move})`).click();
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the test is similar to the previous one.&lt;/p&gt;
&lt;p&gt;Now it&apos;s time to see how you can mock the API.&lt;/p&gt;
&lt;p&gt;First, you have to get your API; to do this, you have to use the &lt;code&gt;page.route&lt;/code&gt; that way.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;page.route(&quot;http://localhost:3001/api/winners&quot;, async route =&amp;gt; {   
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, as you can notice, the &lt;code&gt;page.route&lt;/code&gt; method accepts two parameters: the first is the URL of your API, and the second is a function used to work with your request.&lt;/p&gt;
&lt;p&gt;Now it&apos;s time to get info from your request, for instance, the method and the body of the request.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;page.route(&quot;http://localhost:3001/api/winners&quot;, async route =&amp;gt; {
  const request = route.request();
  const method = await request.method();
  const postData = await request.postDataJSON();
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Very simple, as you can see, it&apos;s important to remember that all the methods of the request return a Promise, and you have to use the await keyword to get the value.&lt;/p&gt;
&lt;p&gt;Now, another important feature when you want to mock API is to return custom responses.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;page.route(&quot;http://localhost:3001/api/winners&quot;, async route =&amp;gt; {
  const request = route.request();
  const method = await request.method();
  const postData = await request.postDataJSON();

  await route.fulfill({
    status: 200,
    contentType: &quot;application/json&quot;,
    body: JSON.stringify(Object.assign({ id: 1 }, postData)),
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using &lt;code&gt;route.fulfill&lt;/code&gt; you can mock the response. You can set the status code, content type, body, etc. In this way, you have all the power to work with the response.&lt;/p&gt;
&lt;p&gt;Perfect, you have all the tools to mock the request. But before closing, I want to leave you another tip. You can use the &lt;code&gt;page.route&lt;/code&gt; as the assertion of your test.&lt;/p&gt;
&lt;p&gt;Let&apos;s see an example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;page.route(&quot;http://localhost:3001/api/winners&quot;, async route =&amp;gt; {
  const request = route.request();
  const method = await request.method();
  const postData = await request.postDataJSON();

  expect(await request.method()).toBe(&quot;POST&quot;);
  expect(await request.postDataJSON()).toEqual(
    expect.objectContaining({
      winner: expect.stringMatching(&quot;X&quot;),
      createdAt: expect.any(String),
    })
  );

  await route.fulfill({
    status: 200,
    contentType: &quot;application/json&quot;,
    body: JSON.stringify(Object.assign({ id: 1 }, postData)),
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, you can use the &lt;code&gt;expect&lt;/code&gt; function also inside of the &lt;code&gt;page.route&lt;/code&gt;. So you can check if the request is called and in the right way.&lt;/p&gt;
&lt;p&gt;To close the article, here you can find the entire test.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test(&quot;should register the winner calling the winner API[POST]&quot;, async ({
  page,
  playerXWinMoves,
}) =&amp;gt; {
  page.route(&quot;http://localhost:3001/api/winners&quot;, async route =&amp;gt; {
    const request = route.request();
    const method = await request.method();
    const postData = await request.postDataJSON();

    await route.fulfill({
      status: 200,
      contentType: &quot;application/json&quot;,
      body: JSON.stringify(Object.assign({ id: 1 }, data)),
    });

    expect(await request.method()).toBe(&quot;POST&quot;);
    expect(await request.postDataJSON()).toEqual(
      expect.objectContaining({
        winner: expect.stringMatching(&quot;X&quot;),
        createdAt: expect.any(String),
      })
    );
  });

  for (const move of playerXWinMoves) {
    await page.locator(`button:nth-child(${move})`).click();
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok, I think that&apos;s all from Mocking API. Now you have all the notions to start mocking API with Playwright, and if you have any doubt, you can reach out to me without problems or check the official &lt;a href=&quot;https://playwright.dev/docs/mock&quot;&gt;documentation&lt;/a&gt;.&lt;br /&gt;
I hope you enjoyed this content.&lt;/p&gt;
&lt;p&gt;See you soon folk!&lt;/p&gt;
&lt;p&gt;Bye bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this article&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/playwright-series/tree/08-mockapi&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>e2e</category><category>mocking</category><category>api</category></item><item><title>Playwright - CI</title><link>https://delpuppo.net/blog/playwright/playwright-ci/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-ci/</guid><description>Hi there, Today I want to speak about integrating Playwright in your GitHub action CI. So don&apos;t waste...</description><pubDate>Thu, 19 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi there,&lt;br /&gt;
Today I want to speak about integrating Playwright in your GitHub action CI.&lt;br /&gt;
So don&apos;t waste time and let&apos;s start.&lt;/p&gt;
&lt;p&gt;To start, you have to create a file called &lt;code&gt;playwright.yml&lt;/code&gt; in this path &lt;code&gt;.github/workflows&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;.github/workflows&lt;/code&gt;&apos; path is used to save the files for your GitHub Actions, and the name of the file is not important for GitHub because the value for it is inside of your files.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let&apos;s start to copy and paste this code into the playwright.yml&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name: Playwright Tests
on: [push]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These two info are used to give a name to the CI and to define what triggers this CI.&lt;br /&gt;
These are standard fields that you can find in every GitHub Action in the world.&lt;br /&gt;
In this case, the CI will trigger every push in the project.&lt;/p&gt;
&lt;p&gt;Now it&apos;s time to add the first job to run your e2e tests in CI.&lt;br /&gt;
To do that, add this to your file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;jobs:
  test-e2e:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 16
      - name: Install dependencies
        run: npm ci
      - name: Install Playwright Browsers
        run: npx playwright install --with-deps
      - name: Run Playwright tests
        run: npx playwright test
      - uses: actions/upload-artifact@v3
        if: always()
        with:
          name: playwright-e2e-report
          path: playwright-report/
          retention-days: 30
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jobs are used in GitHub Action to run different stuff, like build, test, deploy etc. etc.&lt;br /&gt;
In this example, the &lt;code&gt;test-e2e&lt;/code&gt;&apos;s job creates a list of steps to run the test in the CI.&lt;br /&gt;
But what this job does:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;runs-on&lt;/code&gt; is used to indicate on which platform the job has to run&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;actions/checkout@v3&lt;/code&gt; checkouts the code&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;actions/setup-node@v3&lt;/code&gt; setups the node version for the job&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Install dependencies&lt;/code&gt; installs all the dependencies in the &lt;code&gt;node_modules&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Install Playwright Browsers&lt;/code&gt; installs the browsers for Playwright&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Run Playwright tests&lt;/code&gt; runs the e2e tests&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;actions/upload-artifact@v3&lt;/code&gt; uploads the test&apos;s results in the GitHub Artifact&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ok, this is the job for the e2e tests; now it&apos;s time to add the job for the component tests.&lt;br /&gt;
To do that, copy and paste the following code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  test-ct:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 16
      - name: Install dependencies
        run: npm ci
      - name: Install Playwright Browsers
        run: npx playwright install --with-deps
      - name: Run Playwright tests
        run: npx playwright test -c playwright-ct.config.ts
      - uses: actions/upload-artifact@v3
        if: always()
        with:
          name: playwright-ct-report
          path: playwright-report/
          retention-days: 30
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, it&apos;s similar to the previous job but has different configurations, so I don&apos;t dive into it.&lt;br /&gt;
Now with these two jobs, you have a CI ready to run.&lt;br /&gt;
To do that, &lt;code&gt;git add&lt;/code&gt; + &lt;code&gt;git commit&lt;/code&gt; + &lt;code&gt;git push&lt;/code&gt;, and go into your online GitHub repository. In the tab Actions, you can find your CI in action, and If you click on it, you can see the two jobs running. (It&apos;s important to understand that these two jobs run in parallel, you can find more info about job execution &lt;a href=&quot;https://docs.github.com/en/actions/using-jobs/using-jobs-in-a-workflow&quot;&gt;in the GitHub repository&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;When the CI is ended, you are sure that your tests are ok as expected. And the result will be like this.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Perfect, now you have your first GitHub action configured to run your tests with Playwright.&lt;/p&gt;
&lt;p&gt;Good, that&apos;s all folk, I think you have all the info to integrate Playwright in your CI without any problem.&lt;/p&gt;
&lt;p&gt;Thank you and see you soon.&lt;/p&gt;
&lt;p&gt;Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The code of this post is available&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/playwright-series/tree/07-ci&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>testing</category><category>github</category><category>githubaction</category></item><item><title>Playwright - Components testing</title><link>https://delpuppo.net/blog/playwright/playwright-components-testing/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-components-testing/</guid><description>Hi there, Today I&apos;ll speak about a beta feature in Playwright: Components. The team is building a...</description><pubDate>Thu, 12 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi there,&lt;br /&gt;
Today I&apos;ll speak about a beta feature in Playwright: Components.&lt;/p&gt;
&lt;p&gt;The team is building a new feature to write component tests with Playwright, so it&apos;s time to see how it works.&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;To start to use this feature, you have to install it. To do that, type in your terminal&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm init playwright@latest -- --ct
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The command asks you two questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Which framework do you use? (experimental)&lt;/strong&gt;
choose to &lt;em&gt;react&lt;/em&gt; to this tutorial&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install Playwright browsers
choose to &lt;em&gt;true&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When the installation ends, there will be a new file in your project called: &lt;code&gt;playwright-ct.config.ts&lt;/code&gt;. This file contains the configuration for the components&apos; testing.&lt;br /&gt;
For this tutorial, you have to change only one configuration, &lt;code&gt;testDir&lt;/code&gt; property from &lt;code&gt;./&lt;/code&gt; to &lt;code&gt;./src&lt;/code&gt;. Playwright uses this configuration to understand where the files used for the components&apos; tests are located. In this example, you&apos;ll put the test file in the same folder as the component.&lt;/p&gt;
&lt;h2&gt;First Test&lt;/h2&gt;
&lt;p&gt;Let&apos;s start with the first component test.&lt;/p&gt;
&lt;p&gt;Create a file called &lt;code&gt;Icon.spec.tsx&lt;/code&gt; in the folder &lt;code&gt;src/components/Icon/&lt;/code&gt;, and inside of it, copy this code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { expect, test } from &apos;@playwright/experimental-ct-react&apos;;
import Icon from &apos;./Icon&apos;;

test.use({ viewport: { width: 500, height: 500 } });

const props = {
  src: &apos;src&apos;,
  title: &apos;title&apos;,
}

test(&apos;should work&apos;, async ({ mount }) =&amp;gt; {
  const component = await mount(&amp;lt;Icon src={props.src} title={props.title} /&amp;gt;);
  await expect(component).toHaveAttribute(&apos;src&apos;, &apos;src&apos;);
  await expect(component).toHaveAttribute(&apos;title&apos;, props.title);
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the structure is similar to other Testing Frameworks.&lt;br /&gt;
You have to import the methods relative to react components from the path &lt;code&gt;@playwright/experimental-ct-react&lt;/code&gt; and import your component.&lt;br /&gt;
Then you can set up the viewport for your test; it&apos;s important to understand that the tests run in different browsers, so you can also test your components in different viewports. And at the end, it&apos;s time to check your component.&lt;br /&gt;
The test structure is straightforward; using the &lt;code&gt;mount&lt;/code&gt; method, you can render the component in the DOM, and then you can check the result using the Playwright APIs.&lt;br /&gt;
For instance, in this case, the test checks if the &lt;code&gt;src&lt;/code&gt; and &lt;code&gt;title&lt;/code&gt; attributes have the correct value.&lt;br /&gt;
Using these tests, you can check the proper logic or the right representation of your components and guarantee the right render in different browsers.&lt;/p&gt;
&lt;h2&gt;Run the test&lt;/h2&gt;
&lt;p&gt;Cool, you set up Playwright, and you wrote the tests. Now it&apos;s time to run it.&lt;br /&gt;
Easy peasy lemon squeezy, type in your terminal the following command&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx playwright test -c playwright-ct.config.ts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx playwright show-report
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the result is like this.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;As you can notice, Playwright runs the test in three different browsers by default. You can decide where to run the tests, adding or removing the browsers from the configuration file.&lt;/p&gt;
&lt;p&gt;Perfect! I think you have a good introduction to component testing with Playwright. The feature is in experimental mode, so use it carefully, please.&lt;br /&gt;
You can find out more info in the official &lt;a href=&quot;https://playwright.dev/docs/test-components&quot;&gt;documentation&lt;/a&gt; if you want to dive into it.&lt;/p&gt;
&lt;p&gt;I hope you enjoyed this content.&lt;br /&gt;
See you soon folk.&lt;/p&gt;
&lt;p&gt;Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this post&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/playwright-series/tree/06-components&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>components</category><category>testing</category></item><item><title>Visual Studio Code - Tips &amp; Tricks - Profile</title><link>https://delpuppo.net/blog/vs-code-tips-and-tricks/visual-studio-code-tips-tricks-profile/</link><guid isPermaLink="true">https://delpuppo.net/blog/vs-code-tips-and-tricks/visual-studio-code-tips-tricks-profile/</guid><description>Intro During my daily work, sometimes I have to switch between different projects: backend...</description><pubDate>Tue, 10 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Intro&lt;/h2&gt;
&lt;p&gt;During my daily work, sometimes I have to switch between different projects: backend frontend, nodejs, react, angular etc. etc.&lt;/p&gt;
&lt;p&gt;I used to think that configuring VsCode in the best way for each project was impossible. In addition, Im a bit drug of extensions in my VsCode, which often causes performance decreases because some unused extensions (not required for the current project) use a lot of RAM or CPU. To go around this problem, typically, I used to disable these extensions but with the cons that I have to reenable them when I need to work with them. It was a bit frustrating, but some days ago, I came across a fantastic feature of VsCode. This feature is called Profile. Currently, the feature is present only in the &lt;a href=&quot;https://code.visualstudio.com/insiders/&quot;&gt;Insider&lt;/a&gt;, but I hope it will become available to all early.&lt;/p&gt;
&lt;h2&gt;What is Profile?&lt;/h2&gt;
&lt;p&gt;Profile allows you to create different setups in base on your needs. Using a profile, you can have different setups based on the current language, include or exclude extensions, change shortcuts, etc. etc.&lt;/p&gt;
&lt;h2&gt;How can you set up your profile?&lt;/h2&gt;
&lt;p&gt;To work with profiles, you have to make your focus on the bottom-left of your editor. There is an icon where you can handle your profile. The default profile is called, as you can imagine, Default. If you have never heard about Profile before now, it goes without saying that you have the Default profile selected. But now, its time to learn how it works.&lt;/p&gt;
&lt;p&gt;Its not rocket science, but its very helpful, in my opinion.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Create a new Profile&lt;/h3&gt;
&lt;p&gt;You must click the Profile section and select Create New Profile to create a new one. Now you can choose between two options: an empty configuration or starting from another profile. Now the decision is in your hands. Add, remove, and change your configuration as you want in base on your needs. For instance, I created different setups based on the context: AWS, Azure, Node, Angular, and React. You can find your best solution to improve your productivity.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Delete Profile&lt;/h3&gt;
&lt;p&gt;Delete profile is easy peasy; click on the Profile section and select &quot;Delete Profile&quot;, then you have to choose the Profile that you want to delete (one or many) and click the Ok button. Now the game is done, the profile will be removed.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In my opinion, this feature is essential. I created my setups, and now VsCode works quickly and without performance problems. I hope it will be the same for you too.&lt;br /&gt;
Creating different Profiles allows me to create my best experience during my daily routine with VsCode and reduce the possibility of wasting time with performance problems created by extension that are useless at that moment.&lt;/p&gt;
&lt;p&gt;I hope this content could be helpful for you too. Let me know in the comment if you already know it or if you will be surprised like me when I discovered it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>vscode</category><category>code</category></item><item><title>Playwright - Fixtures</title><link>https://delpuppo.net/blog/playwright/playwright-fixtures/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-fixtures/</guid><description>Hey there, Today I want to speak about Fixtures, a vital friend if you&apos;re going to work with...</description><pubDate>Thu, 05 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey there,&lt;br /&gt;
Today I want to speak about Fixtures, a vital friend if you&apos;re going to work with Playwright and you want to share data between your tests or create custom executions.&lt;/p&gt;
&lt;p&gt;Let&apos;s start with a simple example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test(&apos;should win the player &quot;X&quot;&apos;, async ({ page }) =&amp;gt; {
  await page.goto(&quot;/&quot;);
  await page.locator(&quot;button:nth-child(1)&quot;).click();
  await page.locator(&quot;button:nth-child(5)&quot;).click();
  await page.locator(&quot;button:nth-child(6)&quot;).click();
  await page.locator(&quot;button:nth-child(7)&quot;).click();
  await page.locator(&quot;button:nth-child(3)&quot;).click();
  await page.locator(&quot;button:nth-child(9)&quot;).click();
  await page.locator(&quot;button:nth-child(2)&quot;).click();

  const winnerParagraph = await page.getByText(/winner/i);
  await expect(winnerParagraph).toContainText(&quot;X&quot;);
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Imagine you want to extract all the indexes of the buttons in an array to replicate this test and reduce all these click commands to have a shorter test.&lt;br /&gt;
So, the first refactor before introducing the fixture feature could be this.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test(&apos;should win the player &quot;X&quot;&apos;, async ({ page }) =&amp;gt; {
  const playerXWinMoves = [1, 5, 6, 7, 3, 9, 2];

  for (const move of playerXWinMoves) {
    await page.locator(`button:nth-child(${move})`).click();
  }

  const winnerParagraph = await page.getByText(/winner/i);
  await expect(winnerParagraph).toContainText(&quot;X&quot;);
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, all the steps to reproduce the players&apos; moves are contained in the &lt;code&gt;playerXWinMoves&lt;/code&gt; variables. The test is concise, but most important, all the actions are in a single variable. Now it&apos;s time to introduce fixtures.&lt;/p&gt;
&lt;p&gt;Before carrying on, let me spend some words describing what fixtures are.&lt;/p&gt;
&lt;h2&gt;What fixtures are&lt;/h2&gt;
&lt;p&gt;Test fixtures are used to establish an environment for each test, giving the test everything it needs and nothing else. Test fixtures are isolated between tests. With fixtures, you can group tests based on their meaning instead of their standard setup.&lt;br /&gt;
After this definition, you can think fixtures could be replaced by before/after hooks, but fixtures have several advantages over these hooks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Fixtures &lt;strong&gt;encapsulate&lt;/strong&gt; setup and teardown in the same place, making it easier to write.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fixtures are &lt;strong&gt;reusable&lt;/strong&gt; between test files - you can define them once and use them in all your tests. That&apos;s how Playwright&apos;s built-in &lt;code&gt;page&lt;/code&gt; fixture works.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fixtures are &lt;strong&gt;on-demand&lt;/strong&gt; - you can define as many fixtures as you&apos;d like, and Playwright Test will set up only the ones needed by your test and nothing else.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fixtures are &lt;strong&gt;composable&lt;/strong&gt; - they can depend on each other to provide complex behaviours.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fixtures are &lt;strong&gt;flexible&lt;/strong&gt;. Tests can use any combination of fixtures to tailor the precise environment they need without affecting other tests.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fixtures simplify &lt;strong&gt;grouping&lt;/strong&gt;. You no longer need to wrap tests in &lt;code&gt;describe&lt;/code&gt;s that set up an environment and are free to group your tests by their meaning instead.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Perfect, after this boring theoric part, it&apos;s time to get your hands dirty with fixtures in Playwright.&lt;br /&gt;
To start the explanation, I want to begin with the final result.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { expect, test as base } from &quot;@playwright/test&quot;;

type TestFixtures = {
  playerXWinMoves: [number, number, number, number, number, number, number];
};

const test = base.extend&amp;lt;TestFixtures&amp;gt;({
  playerXWinMoves: async ({}, use) =&amp;gt; {
    await use([1, 5, 6, 7, 3, 9, 2]);
  },
});

test(&apos;should win the player &quot;X&quot;&apos;, async ({ page, playerXWinMoves }) =&amp;gt; {
  for (const move of playerXWinMoves) {
    await page.locator(`button:nth-child(${move})`).click();
  }

  const winnerParagraph = await page.getByText(/winner/i);
  await expect(winnerParagraph).toContainText(&quot;X&quot;);
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, to build our fixture, you have to extend the test object exposed by Playwright. Inside this function, you can create an object that represents your fixtures. In this case, I added the &lt;code&gt;playerXWinMoves&lt;/code&gt; property to share the steps to reproduce the Player X win. In addition, just because I love working with Typescript, I added the &lt;code&gt;TestFixtures&lt;/code&gt; type to describe my fixtures. It&apos;s essential to notice that inside the fixture, you must use the &lt;code&gt;use&lt;/code&gt; method to set the value for your fixtures.&lt;br /&gt;
Ok, carry on and let&apos;s take a look at the test now. You can notice that you can get the &lt;code&gt;playerXWinMoves&lt;/code&gt; fixture directly from the object passed to your test. And now, if you remove the previous variable and use the new one from the params, you will create your first test with Playwright using fixture.&lt;br /&gt;
Great, I hope you can understand the incredible power of this feature and how it can help you to make your test more readable or to bring together some data useful in many tests.&lt;br /&gt;
But before closing, let me leave you another bit. With fixtures, you can also override an object exposed directly by Playwright. For instance, you can override the page object, and instead of creating a &lt;code&gt;beforeEach&lt;/code&gt; hook to navigate to the home page, you can override the page and add this step in a fixture, so every test, before its execution, runs the steps to navigate to the home page.&lt;br /&gt;
And how can we do that? Simply in this way.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const test = base.extend&amp;lt;TestFixtures&amp;gt;({
  page: async ({ baseURL, page }, use) =&amp;gt; {
    baseURL &amp;amp;&amp;amp; (await page.goto(baseURL));
    await use(page);
  },
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Doing that, now each test, when it starts its execution, goes to the baseURL and then runs all the code. Incredible no? Now, you can remove the &lt;code&gt;beforeEach&lt;/code&gt; hook in the test file and rerun your tests to check the result.&lt;/p&gt;
&lt;p&gt;Ok, that&apos;s all folk!&lt;br /&gt;
Today you have learned how Playwright fixtures work and how to build one.&lt;br /&gt;
I hope you enjoyed this post, and if you have any doubts, don&apos;t hesitate to reach out to me; I will be happy to help you.&lt;/p&gt;
&lt;p&gt;See you soon&lt;br /&gt;
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;p.s. you can check out the code of this article&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/playwright-series/tree/05-fixture&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>e2e</category></item><item><title>Playwright - Generate tests&apos; code</title><link>https://delpuppo.net/blog/playwright/playwright-generate-tests-code/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-generate-tests-code/</guid><description>Hi there, today you will learn how to generate the code for your tests. First of all, you have to...</description><pubDate>Thu, 29 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi there,&lt;br /&gt;
today you will learn how to generate the code for your tests.&lt;/p&gt;
&lt;p&gt;First of all, you have to run the application, so type in your terminal &lt;code&gt;npm run dev&lt;/code&gt; , and you will have your application up and running at the address &lt;code&gt;http://localhost:5173&lt;/code&gt;.&lt;br /&gt;
Now you have to run the Playwright code generator. To do that, you have to open another tab in your terminal and type &lt;code&gt;npx playwright codegen&lt;/code&gt;.&lt;br /&gt;
This command opens in your display a new browser and the Playwright inspector.&lt;br /&gt;
Now, the browser shows an empty tab, and the Playwright inspector is on a new page, ready to listen to what you will do in the browser. If you go into the browser&apos;s address bar and type &lt;code&gt;http://localhost:5173,&lt;/code&gt; you can notice that something has changed in the Playwright Inspector. The inspector noted the page change and added this step to the test body. Now, you can click on one square and simulate a game between two players, you can notice that the inspector records all these steps and creates the body of the test for you. The result of these actions is this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test(&apos;test&apos;, async ({ page }) =&amp;gt; {
  await page.goto(&apos;http://localhost:5173/&apos;);
  await page.locator(&apos;._Square_pba4r_1&apos;).first().click();
  await page.locator(&apos;button:nth-child(5)&apos;).click();
  await page.locator(&apos;button:nth-child(6)&apos;).click();
  await page.locator(&apos;button:nth-child(7)&apos;).click();
  await page.locator(&apos;button:nth-child(3)&apos;).click();
  await page.locator(&apos;button:nth-child(9)&apos;).click();
  await page.locator(&apos;button:nth-child(2)&apos;).click();
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the generated code is good but not perfect, so please use this tool with the head on the shoulders and check the result every time to ensure your test&apos;s value.&lt;/p&gt;
&lt;p&gt;Say that, now it&apos;s time to copy and paste the code into our test file and improve its content. Let&apos;s start by changing the test name from &lt;code&gt;test&lt;/code&gt; to &lt;code&gt;should win the player &quot;X&quot;&lt;/code&gt; and changing the goto value from &lt;code&gt;http://localhost:5173/&lt;/code&gt; to &lt;code&gt;/&lt;/code&gt; because our base root corresponds to the home page. Then refactoring the first click probably is a good refactor to improve the test, so you have to change the line from &lt;code&gt;await page.locator(&apos;._Square_pba4r_1&apos;).first().click();&lt;/code&gt; to &lt;code&gt;await page.locator(&quot;button:nth-child(1)&quot;).click();&lt;/code&gt; and last but not least, add the assertion. In this case, if the test name is &lt;code&gt;should win the player &quot;X&quot;&lt;/code&gt; the best assertion is something like this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const winnerParagraph = await page.getByText(/winner/i);
await expect(winnerParagraph).toContainText(&quot;X&quot;);

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So the code tries to get the paragraph with the winner text and checks if the value contains the &lt;code&gt;X&lt;/code&gt; value.&lt;br /&gt;
The final result is this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test(&apos;should win the player &quot;X&quot;&apos;, async ({ page }) =&amp;gt; {
    await page.goto(&quot;/&quot;);
    await page.locator(&quot;button:nth-child(1)&quot;).click();
    await page.locator(&quot;button:nth-child(5)&quot;).click();
    await page.locator(&quot;button:nth-child(6)&quot;).click();
    await page.locator(&quot;button:nth-child(7)&quot;).click();
    await page.locator(&quot;button:nth-child(3)&quot;).click();
    await page.locator(&quot;button:nth-child(9)&quot;).click();
    await page.locator(&quot;button:nth-child(2)&quot;).click();

    const winnerParagraph = await page.getByText(/winner/i);
    await expect(winnerParagraph).toContainText(&quot;X&quot;);
  });

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, you can run the test and check the result which should be green.&lt;/p&gt;
&lt;p&gt;Ok, I think that&apos;s all from the code generation.&lt;br /&gt;
In this article, you learnt how to record your steps and convert them to code for your tests. Please, as I said before, use this tool responsibly and check the generated code every time.&lt;/p&gt;
&lt;p&gt;That&apos;s it, folk.&lt;/p&gt;
&lt;p&gt;See you soon 👋&lt;/p&gt;
&lt;p&gt;p.s. you can find the result of this article &lt;a href=&quot;https://github.com/Puppo/playwright-series/tree/04-code-generator&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>e2e</category></item><item><title>Playwright - debug your tests</title><link>https://delpuppo.net/blog/playwright/playwright-debug-your-tests/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-debug-your-tests/</guid><description>Debug your tests One of the most popular things done by developers is to debug the code...</description><pubDate>Wed, 21 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Debug your tests&lt;/h2&gt;
&lt;p&gt;One of the most popular things done by developers is to debug the code using &lt;code&gt;console.log&lt;/code&gt;.&lt;br /&gt;
But today I want to show you how to debug your Playwright tests.&lt;/p&gt;
&lt;p&gt;Let&apos;s start with the Playwright Inspector.&lt;br /&gt;
Using the option &lt;code&gt;--debug&lt;/code&gt; when you run the tests, Playwright opens two new windows in your display, a browser and the Playwright Inspector.&lt;br /&gt;
To try this, you can type in your terminal this command &lt;code&gt;npx playwright test --debug&lt;/code&gt;, the result seems like this&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;You can use the commands in the inspector to move forward in the test and check the stuff.&lt;/p&gt;
&lt;p&gt;Cool, but I prefer debugging the tests directly from my editor (VsCode). To do that, you have to install the official extension called &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ms-playwright.playwright&quot;&gt;Playwright Test for VSCode&lt;/a&gt;. The extension permits you to install Playwright in your projects or add new browsers configuration, but today the goal is the debug feature.&lt;br /&gt;
Now, in VsCode if you open the Test Explorer, you can see all your tests in the projects and run them or debug them directly from your editor. Here is an example.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Ok, now it&apos;s time to see how you can run or debug your test directly from VsCode.&lt;br /&gt;
First of all, using the command in the top right of the Test Explorer panel, you can decide between running or debugging all the tests in your suite. Clicking on the arrow on the left of these buttons, you can also decide in which browser you want to run your tests. Here is a short demo!&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In this example, you can see how the runner works, but now it&apos;s time to see how it&apos;s possible to debug tests.&lt;br /&gt;
Let&apos;s start adding a break-point in the code base. If you are not familiar with this in VsCode, it&apos;s elementary, click with the mouse on the left of the line where you want the debugger stops its execution.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://youtu.be/QIryVOtMXvM&quot;&gt;https://youtu.be/QIryVOtMXvM&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, it&apos;s time to debug the test. We will see two methods to debug the tests; the first runs all the tests, and the second runs only the necessary test.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Debug all the tests&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Using the icon in the top-right of the test explorer, you can run all your tests in debug mode, and for each test with a break-point, VsCode can stop the execution and permits you to check the test&apos;s status. Here is a video example of that.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://youtu.be/F5L-qpg3UBA&quot;&gt;https://youtu.be/F5L-qpg3UBA&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is a good example, but typically, you want to debug one test per time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Debug only needed test&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To do that, the flow is very similar, you have to choose which test you want to debug and insert a break-point where you want the execution will stop. Then in Test Explorer, you have to search for your test; you can type the name of your test in the search bar, or you can scroll through the three and find it using the mouse. To run your test now, you must press the icon relative to the debug execution on the right of the test name. Doing that, VsCode will run your test and will stop the execution when the code arrives at the break-point. Here, you can check your application&apos;s status and the problems in your test. Using the command in the top-right of the VsCode&apos;s window, you can move on in the execution.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://youtu.be/68mH0VsjV4M&quot;&gt;https://youtu.be/68mH0VsjV4M&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As you can see, if you are playing with the Test Explorer, you can run or debug all the tests or a specific one. The same approach exists for groups of tests too, so you can run or debug a bunch of tests in the same &lt;code&gt;describe&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ok, I spent an entire article showing you how you can run or debug tests using VsCode because many times I see people that don&apos;t know how to debug, and they spend a lot of time finding the problem and fixing the test. Now you have all the tools to debug your tests with Playwright, so you can check and fix tests quickly.&lt;/p&gt;
&lt;p&gt;That&apos;s it for today; you have learnt how to run and debug tests with Playwright; before using the Playwright inspector and then directly from VsCode.&lt;br /&gt;
I hope you enjoy this content, and if you have any questions, don&apos;t hesitate to reach out to me.&lt;/p&gt;
&lt;p&gt;See you soon, folk&lt;/p&gt;
&lt;p&gt;Bye bye&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>e2e</category><category>vscode</category><category>extensions</category></item><item><title>Playwright - How to write tests</title><link>https://delpuppo.net/blog/playwright/playwright-how-to-write-tests/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-how-to-write-tests/</guid><description>What are you going to learn in this post? In this post, you will learn how to write tests...</description><pubDate>Wed, 14 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;What are you going to learn in this post?&lt;/h2&gt;
&lt;p&gt;In this post, you will learn how to write tests with Playwright, using assertions, locators and something else.&lt;/p&gt;
&lt;h2&gt;Write tests&lt;/h2&gt;
&lt;p&gt;Let&apos;s start with an example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test(&apos;the first player must be the &quot;X&quot; player&apos;, async ({ page }) =&amp;gt; {
  await page.goto(&quot;/&quot;);

  const playerParagraph = await page.getByRole(&quot;paragraph&quot;);

  await expect(playerParagraph).toContainText(&quot;X&quot;);
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, I introduced two new stuff, &lt;code&gt;getByRole&lt;/code&gt; and &lt;code&gt;toContainText&lt;/code&gt;.&lt;br /&gt;
&lt;code&gt;getByRole&lt;/code&gt; is part of the &lt;em&gt;locators&lt;/em&gt; and &lt;code&gt;toContainText&lt;/code&gt; is part of the &lt;em&gt;assertions&lt;/em&gt;, and now we will dive into these new things.&lt;/p&gt;
&lt;h3&gt;Locators&lt;/h3&gt;
&lt;p&gt;Locators are the central piece of Playwright&apos;s auto-waiting and retry-ability. Locators represent a way to find element(s) on the page at any moment.&lt;/p&gt;
&lt;p&gt;Using locators, you can retrieve elements in your dom by these commands:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;page.getByRole(role[, options])&lt;/strong&gt; to locate by explicit and implicit accessibility attributes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;page.getByText(text[, options])&lt;/strong&gt; to locate by text content.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;page.getByLabel(text[, options])&lt;/strong&gt; to locate a form control by associated label&apos;s text.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;page.getByPlaceholder(text[, options])&lt;/strong&gt; to locate an input by placeholder.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;page.getByAltText(text[, options])&lt;/strong&gt; to locate an element, usually image, by its text alternative.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;page.getByTitle(text[, options])&lt;/strong&gt; to locate an element by its title attribute.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;page.getByTestId(testId)&lt;/strong&gt; to locate an element based on its &lt;code&gt;data-testid&lt;/code&gt; attribute (other attributes can be configured).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;page.locator(selector)&lt;/strong&gt; to locate an element base on its selected (Css or XPath)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can see, using these eight commands, you can find all the elements on your pages. Watching the previous example, you can view how using the &lt;code&gt;getByRole&lt;/code&gt; method you can get the paragraph in your DOM and then check whatever you want. Okay, so a quick recap of what locators are: locators are methods that help you to search the elements in the DOM.&lt;/p&gt;
&lt;h3&gt;Assertions&lt;/h3&gt;
&lt;p&gt;Like any test framework that is respected, Playwright has its assertions. Assertions are used to check our results, and as developers, we use them to be sure the application or the code runs as expected. Playwright for this feature uses under the hood the &lt;a href=&quot;https://jestjs.io/docs/expect&quot;&gt;expect&lt;/a&gt; function built by jest. So if you are familiar with &lt;a href=&quot;https://jestjs.io/&quot;&gt;jest&lt;/a&gt;, you won&apos;t have problems with Playwright. The most famous assertions that you can use are: &lt;code&gt;toEqual&lt;/code&gt;, &lt;code&gt;toContain&lt;/code&gt;, &lt;code&gt;toMatch&lt;/code&gt;, &lt;code&gt;toBe&lt;/code&gt; and many more. The assertions are your best friends to check if your application runs as expected.&lt;/p&gt;
&lt;p&gt;As you can imagine, the combination of these two things permits you to build many tests to check the behaviours of your application.&lt;/p&gt;
&lt;p&gt;So if you go back to the previous example and type &lt;code&gt;npm run e2e&lt;/code&gt; in your terminal, you get the following result.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; npm run e2e

&amp;gt; react-e2e@0.0.0 e2e
&amp;gt; playwright test

Running 6 tests using 4 workers

  6 passed (5s)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Wow, it works. 😀 And now you know what to use to create your tests with Playwright.&lt;/p&gt;
&lt;h2&gt;Isolate your tests&lt;/h2&gt;
&lt;p&gt;If you are familiar with testing frameworks, you probably know there is a way to group a test list. To do that with Playwright, you have to use the &lt;code&gt;describe&lt;/code&gt; method exposed by the &lt;code&gt;test&lt;/code&gt; object, as in the following example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { expect, test } from &quot;@playwright/test&quot;;

test.describe(&quot;On View&quot;, () =&amp;gt; {
  test(&quot;show tic tac toe page&quot;, async ({ page }) =&amp;gt; {
    await page.goto(&quot;/&quot;);

    await expect(page).toHaveTitle(&quot;Tic Tac Toe&quot;);
  });

  test(&apos;the first player must be the &quot;X&quot; player&apos;, async ({ page }) =&amp;gt; {
    await page.goto(&quot;/&quot;);

    const playerParagraph = await page.getByRole(&quot;paragraph&quot;);

    await expect(playerParagraph).toContainText(&quot;X&quot;);
  });
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The benefit of grouping is also visible in the report that now appears so.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the label &lt;code&gt;On View&lt;/code&gt; is present before each test.&lt;br /&gt;
So now, you can split your test file into different contexts if you have this need.&lt;/p&gt;
&lt;h2&gt;Hooks&lt;/h2&gt;
&lt;p&gt;Another critical feature if you love working with test frameworks is hooks.&lt;br /&gt;
Hooks allow you to run a piece of code before or after the test execution. Typically they are called: &lt;code&gt;beforeEach&lt;/code&gt; &lt;code&gt;beforeAll&lt;/code&gt; &lt;code&gt;afterEach&lt;/code&gt; &lt;code&gt;afterAll&lt;/code&gt; and you know what they are called in Playwright? Precisely in the same way 🚀&lt;/p&gt;
&lt;p&gt;So, to give an example, you can refactor the code in this way to navigate the home page before each test.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { expect, test } from &quot;@playwright/test&quot;;

test.describe(&quot;On View&quot;, () =&amp;gt; {
  test.beforeEach(async ({ page }) =&amp;gt; {
    await page.goto(&quot;/&quot;);
  });

  test(&quot;show tic tac toe page&quot;, async ({ page }) =&amp;gt; {
    await expect(page).toHaveTitle(&quot;Tic Tac Toe&quot;);
  });

  test(&apos;the first player must be the &quot;X&quot; player&apos;, async ({ page }) =&amp;gt; {
    const playerParagraph = await page.getByRole(&quot;paragraph&quot;);

    await expect(playerParagraph).toContainText(&quot;X&quot;);
  });
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result is the same as before, but now you only have the navigation command inside the &lt;code&gt;beforeEach&lt;/code&gt; hook.&lt;br /&gt;
These hooks are great if you have to mock API or if you have to do something before or after tests.&lt;/p&gt;
&lt;h2&gt;Play with your DOM&lt;/h2&gt;
&lt;p&gt;After all these things, it&apos;s time to write the last test of this post.&lt;br /&gt;
Now you will write a test that simulates the user&apos;s behaviours in the applications. The test simulates the click of the player &quot;X&quot; in the top left square and then checks if the next player is the &quot;O&quot;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test.describe(&quot;Users behaviours&quot;, () =&amp;gt; {
  test.beforeEach(async ({ page }) =&amp;gt; {
    await page.goto(&quot;/&quot;);
  });

  test(&apos;the first player select the top-left square and then the next player is the &quot;O&quot;&apos;, async ({
    page,
  }) =&amp;gt; {
    const squares = await page.getByRole(&quot;button&quot;);

    const topLeftSquare = squares.first();
    await topLeftSquare.click();
    const topLeftSquareImg = await topLeftSquare.getByRole(&quot;img&quot;);

    await expect(topLeftSquareImg).toHaveAttribute(&quot;title&quot;, &quot;X&quot;);
    await expect(topLeftSquareImg).toHaveAttribute(&quot;src&quot;, /x.png/i);

    const playerParagraph = await page.getByRole(&quot;paragraph&quot;);

    await expect(playerParagraph).toContainText(&quot;O&quot;);
  });
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This example starts to become trickier. As you can notice, there are some new things. Let&apos;s start with the first one, the &lt;code&gt;first&lt;/code&gt; method. In this case, the &lt;code&gt;getByRole&lt;/code&gt; returns many elements, and only the first is required in the test. Using the &lt;code&gt;first&lt;/code&gt; method, you can get the first element in the list.&lt;br /&gt;
Then when you have the first square on the board, you can simulate the click of this element by the user. Using the &lt;code&gt;click&lt;/code&gt; method, you can do that. Easy peasy lemon squeezy. But now things start to become &quot;complex&quot;. As you can see, now you can use the &lt;code&gt;getByRole&lt;/code&gt; from the square element, and the method tries to find an image child of this element. After that, using &lt;code&gt;toHaveAttribute&lt;/code&gt; assertion, you check if this image has a title with the &quot;X&quot; value and if the source contains the value &quot;x.png&quot;. The final step is the same as in the previous post, where you get the paragraph and check if the next player is now the &quot;O&quot; player. Ok, it&apos;s not rocket science but a bit more complicated than the previous example.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Ok, I think you have materials to study for now! 😃&lt;br /&gt;
So, what you have learned in this post:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Locators&lt;/li&gt;
&lt;li&gt;Assertions&lt;/li&gt;
&lt;li&gt;How to isolate your test&lt;/li&gt;
&lt;li&gt;Hooks&lt;br /&gt;
I suggest you get your hand dirty with these topics because they will be the fundamentals of your test with Playwright.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ok, that&apos;s all folk, see you soon.&lt;br /&gt;
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;P.s. you can find the result of this post at this&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/playwright-series/tree/02-how-to-write-tests&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>e2e</category></item><item><title>Playwright - Let&apos;s start</title><link>https://delpuppo.net/blog/playwright/playwright-lets-start/</link><guid isPermaLink="true">https://delpuppo.net/blog/playwright/playwright-lets-start/</guid><description>In the last period, in the frontend ecosystem, a new e2e tool has come up and it has started to...</description><pubDate>Wed, 07 Dec 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the last period, in the frontend ecosystem, a new e2e tool has come up and it has started to become famous; its name is Playwright. In this short series, I want to leave you with some information on this and tips on how to get started.&lt;/p&gt;
&lt;h2&gt;What is it?&lt;/h2&gt;
&lt;p&gt;Let&apos;s start with what Playwright is. Playwright is a testing framework to handle e2e testing. With Playwright we can write e2e tests and run them in different browsers, like Chrome, Firefox and Webkit. We can run our tests on many platforms like Windows, Mac, Linux or CI, and we can write tests in Typescript, Javascript, Java, Phyton or .Net.&lt;/p&gt;
&lt;p&gt;If you open the official &lt;a href=&quot;https://playwright.dev/&quot;&gt;website&lt;/a&gt;, you can find these characteristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Any browser Any platform One API&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Resilient No flaky tests&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No trade-offs No limits&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Full isolation Fast execution&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Powerful Tooling&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In my opinion, the tool reflects all of these characteristics.&lt;/p&gt;
&lt;h2&gt;TicTacToe application&lt;/h2&gt;
&lt;p&gt;I want to use a TicTacToe application built with vite + react in this series. And you can find it &lt;a href=&quot;https://github.com/Puppo/playwright-series/tree/00-the-app&quot;&gt;in the GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the application is straightforward, but with it, we can start to move to the first steps with Playwright.&lt;/p&gt;
&lt;h2&gt;Install Playwright&lt;/h2&gt;
&lt;p&gt;The first step to use Playwright is installing it, that is easy. Open your terminal and type &lt;code&gt;npm init playwright@latest&lt;/code&gt; (I use npm but if you want to use yarn or pnpm read the &lt;a href=&quot;https://playwright.dev/docs/intro#installing-playwright&quot;&gt;docs&lt;/a&gt;). Ok, now the installation asks you some questions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Where to put your end-to-end tests? The default option is &lt;code&gt;tests&lt;/code&gt; but I prefer to use the folder &lt;code&gt;e2e&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add a GitHub Actions workflow? The default option is &lt;code&gt;false&lt;/code&gt;; in this demo, I leave this option to false for now.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install Playwright browsers (can be done manually via &apos;npx playwright install&apos;)? The default option is &lt;code&gt;true&lt;/code&gt;, and I used this value&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;and now you have to wait until the installation ends. When the installation is completed... congratulation, you are ready to get your hands dirty with Playwright!&lt;/p&gt;
&lt;h2&gt;First Look&lt;/h2&gt;
&lt;p&gt;The installation created in your repository 3 new files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;playwright.config.ts&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;e2e/example.spec.ts&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;tests-examples/demo-todo-app.spec.ts&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&apos;s start with the last one, the easiest 😊 This file contains a list of examples of how you can write tests with Playwright. It uses an application created by the playwright team (a simple to-do app) and illustrates how you can interact with your page.&lt;/p&gt;
&lt;p&gt;Carrying on with the second one. This file is a quick example of some tests on the playwright website, but it&apos;s here only as a placeholder for your tests.&lt;/p&gt;
&lt;p&gt;And now, the first one, the most important. Playwright uses the &lt;code&gt;playwright.config.ts&lt;/code&gt; file to understand its configuration. Inside it, you can find configurations about the test folder, the timeout used by the expect function, the configurations for the browsers used by Playwright to run the tests, and more.&lt;/p&gt;
&lt;h2&gt;Run your first test&lt;/h2&gt;
&lt;p&gt;It&apos;s time to see Playwright in action, so open your terminal again and run the following command &lt;code&gt;npx playwright test&lt;/code&gt;. The result is something like this&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Playwright in this report shows you the result of its execution, and you can check if everything has gone ok. The report shows the result for each browser indicated in the configuration, in this case: Chromium, Firefox and Webkit.&lt;/p&gt;
&lt;h2&gt;Write your first test&lt;/h2&gt;
&lt;p&gt;Ok cool, but now it&apos;s time for you to write your first test with Playwright. Before doing this, you have to configure Playwright to be able to run your application before starting with the tests. To do that, you have to open the &lt;code&gt;playwright.config.ts&lt;/code&gt; and add the following configuration&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const config: PlaywrightTestConfig = {
  ...
  webServer: {
    command: &quot;npm run dev&quot;,
    port: 5173,
  },
  ...
};

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;N.B. check your port running the command&lt;/em&gt; &lt;code&gt;npm run dev&lt;/code&gt; you have to use the same port exposed by vite.&lt;/p&gt;
&lt;p&gt;And now it&apos;s time for your first test. Open the file &lt;code&gt;e2e/example.spec.ts&lt;/code&gt; and rename it to &lt;code&gt;e2e/tit-tac-toe.spec.ts&lt;/code&gt;. Then clean everything in the file and leave only the import line &lt;code&gt;import { expect, test } from &quot;@playwright/test&quot;;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now add your first test&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;test(&quot;show tic tac toe page&quot;, async ({ page }) =&amp;gt; {
  await page.goto(&quot;/&quot;);

  await expect(page).toHaveTitle(&quot;Tic Tac Toe&quot;);
});

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ok, let&apos;s see this test together. First of all, you can indicate to Playwright that it is a test using the &lt;code&gt;test&lt;/code&gt; function. As in every testing framework, the test function&apos;s first param is the test&apos;s name. The second param is the function to test our application. Using Playwright, this function is always an async function because your tests in these cases are always asynchronous. The first command in this example is a command to say to Playwright to navigate to the home page of our application. As you can see, already this command is async. Now, if the test can navigate to this page, you want to test if the title of the page is &quot;Tic Tac Toe&quot;. Yes, it&apos;s elementary, but an excellent example of moving your first step.&lt;/p&gt;
&lt;p&gt;Now, it&apos;s time to check if the test runs in Playwright, but before doing that, you can simplify the interaction with Playwright by adding a new script in the package.json, as shown here&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   ....
   &quot;scripts&quot;: {
    ...
    &quot;e2e&quot;: &quot;playwright test&quot;
  },

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;now in your terminal you can type &lt;code&gt;npm run e2e&lt;/code&gt; and voila, your test is gone&lt;/p&gt;
&lt;p&gt;Adding another script in your package.json, you can open the report result in your browser&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   ....
   &quot;scripts&quot;: {
    ...
    &quot;e2e&quot;: &quot;playwright test&quot;,
    &quot;e2e:report&quot;: &quot;playwright show-report&quot;
  },

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now, if you run the command &lt;code&gt;npm run e2e:report&lt;/code&gt; in your browser, you can see the result of your first test.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Ok, I think that&apos;s all for now. In this post, you learnt:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;How to install Playwright&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How to run your test&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How to write your first test with Playwright&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the next post, we will continue our journey in the Playwright world, but for now, that&apos;s all! See you soon, folks.&lt;/p&gt;
&lt;p&gt;Bye Bye&lt;/p&gt;
&lt;p&gt;&lt;em&gt;p.s. You can find the result of this post at this&lt;/em&gt; &lt;a href=&quot;https://github.com/Puppo/playwright-series/tree/01-install-and-run&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;🎬 &lt;strong&gt;Watch / View Embedded Resource:&lt;/strong&gt; &lt;a href=&quot;https://dev.to/puppo&quot;&gt;https://dev.to/puppo&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded><category>playwright</category><category>e2e</category></item><item><title>Be aware of your codebase with Nx</title><link>https://delpuppo.net/blog/be-aware-of-your-codebase-with-nx/</link><guid isPermaLink="true">https://delpuppo.net/blog/be-aware-of-your-codebase-with-nx/</guid><description>Preface Is your team aware of the relations between your modules? Is a team member able to...</description><pubDate>Tue, 29 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Preface&lt;/h2&gt;
&lt;p&gt;Is your team aware of the relations between your modules? Is a team member able to understand what is affected by the changes in a new feature quickly? Probably your answer is: it depends. It depends on the team member and on the time that this team member is on the project. But today I want to show you how you can make your team more confident in your codebase regardless of the seniority or the time he or she is in the project.&lt;/p&gt;
&lt;h2&gt;The problem&lt;/h2&gt;
&lt;p&gt;Imagine a typical first onboarding day in your company. Probably after the introduction and some hours with the HR team the new colleague starts the onboarding stage with a technical team member. The first thing shown is a demo of the software so they start to understand the business value of the project. After that or its coffee break time or its time to see the codebase. After the project&apos;s checkout, your new colleague and you will open the project in your editor or IDE and the first impact with the codebase for your newbie could be like this:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;And now you start to illustrate how the codebase is structured for each folder. Yes, if you are on the project for a while you know much of the code but for your new colleague understanding and remembering all this stuff quickly is not simple. They also want to see which modules are connected and how, but you dont have a tool to see this information quickly. So you will be forced to open many files to know where the imports are, but for your new colleague, these actions will result in tedious unintelligible steps and will not leave the correct information in their mind.&lt;/p&gt;
&lt;p&gt;But is there a way to improve this situation and help the newbie and the boomer of your project to have a picture of the project and get this info quickly anytime?&lt;/p&gt;
&lt;h2&gt;A better onboarding day&lt;/h2&gt;
&lt;p&gt;Ok, your onboarding day could probably be better, and your new colleague could be more confident about the project after the first day. Do you know that a picture is better than thousand words for your mind? Do you know that your mind remembers images better than words? Therefore, what if the first impression of the project for your new colleague could be like this?&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The newbies will be grateful because they have a big picture of the project and by themselves, they can understand the relations in the codebase. But the surprises are not finished; if you click with the mouse on the relation&apos;s arrows, it&apos;s possible to see which file creates the connection between the modules, is it not cool?&lt;/p&gt;
&lt;p&gt;Ok, fantastic, but now you are wondering &quot;How can I do that?&quot; Beah, it&apos;s simple, using &lt;a href=&quot;https://nx.dev/&quot;&gt;Nx&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;What is Nx?&lt;/h2&gt;
&lt;p&gt;Nx is a &lt;strong&gt;Smart&lt;/strong&gt; , &lt;strong&gt;Fast&lt;/strong&gt; , &lt;strong&gt;Extensible&lt;/strong&gt; build System.&lt;/p&gt;
&lt;p&gt;Nx is a tool built by &lt;a href=&quot;https://nrwl.io/&quot;&gt;Nrwl&lt;/a&gt; that allows teams to handle their projects in a great way. One of the goals of Nx is to improve the DevX of teams that work using Monorepo. Nx exposes out-of-the-box for testing: jest, storybook and cypress. Instead, Eslint and Prettier are already configurated to work with the code style. About frameworks, Nx is able to work in the same workspace with React, Angular, WebComponent, and NextJs on the frontend side and with Express, Fastify and NestJS on the backend side. The nrwl team officially maintains these frameworks, but it is also possible to use Nx with other languages or frameworks thanks to the plugins created by the community. Cool!! But Nx doesnt stop here its potential. Nx has an excellent feature called Nx Graph, available by a web application or the Nx Console (an extension created by the nrwl team that works both in VsCode and WebStorm). But lets deepen into Nx Graph.&lt;/p&gt;
&lt;h2&gt;Nx Graph&lt;/h2&gt;
&lt;p&gt;Nx Graph is a web application that shows the tree of your workspace and allows the team to see the state of the codebase. Using the Nx Graph is very simple to check the relations between the modules, and its easy to check the paths between two modules. But Nx doesnt end its power here because it is also able to understand what is changed in your feature branch and detects what is affected by these changes. In these cases, the Nx Graph highlights modules affected by the changes, so you and your team can visualize what could be impacted.&lt;/p&gt;
&lt;p&gt;Nx under the hood uses this information to improve tasks like building and testing. Yes, you read well, it uses this info to enhance the tasks, so Nx is able to build and test only the modules affected by the changes. As you can understand, if your project snowballs, the build and the test time dont increase drastically.&lt;/p&gt;
&lt;h2&gt;Not only for onboarding days&lt;/h2&gt;
&lt;p&gt;The benefits of using Nx are not only during the onboarding days. Using the Nx Graph, your team can see in less time how the project has changed over time or check how the project is growing up. Using Nx is also possible to create rules to prevent relations between modules or tagging modules to develop rules around these tags, but this is another story that we will discover in future.&lt;/p&gt;
&lt;p&gt;Okay, for today, that&apos;s all. I hope you understood this tool&apos;s power and that now you are curious about it. If so, visit the &lt;a href=&quot;https://nx.dev/&quot;&gt;Nx site&lt;/a&gt; and start to take your first steps. If you are curious about the Nx Graph, I suggest you to watch this &lt;a href=&quot;https://youtu.be/ZST_rmhzRXI&quot;&gt;video&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/juristr?s=21&amp;amp;t=yONfiWmu7Y0_OjWAXW13fw&quot;&gt;juri&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you soon with other posts about Nx.&lt;/p&gt;
&lt;p&gt;Bye bye&lt;/p&gt;
</content:encoded><category>nx</category><category>monorepo</category><category>onboarding</category><category>graph</category></item><item><title>Working with GitHub Actions from your best editor</title><link>https://delpuppo.net/blog/vs-code-tips-and-tricks/working-with-github-actions-from-your-best-editor/</link><guid isPermaLink="true">https://delpuppo.net/blog/vs-code-tips-and-tricks/working-with-github-actions-from-your-best-editor/</guid><description>Hi folks, today I&apos;m going to speak about another cool VsCode Extension. In many projects, I love...</description><pubDate>Tue, 08 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi folks,&lt;br /&gt;
today I&apos;m going to speak about another cool VsCode Extension.&lt;/p&gt;
&lt;p&gt;In many projects, I love using &lt;a href=&quot;https://github.com/features/actions&quot;&gt;GitHub Actions&lt;/a&gt; as CI/CD tool, but switching between VsCode and the GitHub website is very boring and frustrating. So, one day I decided to google if there was a way to follow my actions directly in my best Editor, and some minutes later I found this fantastic extension: &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=cschleiden.vscode-github-actions&quot;&gt;GitHub Actions&lt;/a&gt;. This extension and that seen in the previous article have changed my way of working, and now I&apos;m almost free from the browser during my coding phase. I say almost because sometimes I have to check my email or scroll the Twitter wall to stay updated and get the last news 🙂 But let&apos;s see together what this extension is able to do 🚀&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;As with any other extensions, the installation is a piece of cake, you have to open the extensions tab and in the search box you can type &lt;code&gt;GitHub Actions&lt;/code&gt;. There are many extensions with this name but you have to choose the extension created by &lt;code&gt;Christopher Schleiden&lt;/code&gt;, after that, press the install button and wait until the process is ended.&lt;/p&gt;
&lt;h2&gt;Getting started&lt;/h2&gt;
&lt;p&gt;After the installation, the extension asks you to sign in with your GitHub account, so it will be able to read the status of your GitHub Actions.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Okay, press the &quot;Allow&quot; button, enter your GitHub credentials in the browser and follow the instructions to permit VsCode to get the access token for your extension.&lt;/p&gt;
&lt;p&gt;After that, the extension is ready to visualize your actions.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;There are 3 main sections to use this extension:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The icon to open the extension&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The current branch section, where we can see all the actions about our current branch&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Workflows section, where we can see all our workflows and monitor their execution over time&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Run and Watch your Workflow&lt;/h2&gt;
&lt;p&gt;To see the extension in action you have to push your commits into your repository as usual and when the action starts, you can follow its status directly from your Editor, without moving in your browser. Here is a demo.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;As shown in the demo, you can see the status of the action, and for each status, there is a specific icon that represents the state. You are also able to watch the logs by clicking the step of your interest.&lt;/p&gt;
&lt;p&gt;Unfortunately, sometimes opening the browser to see the action on the Github website is necessary, and to do that, there is a fantastic button that opens the browser directly to the action page.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Okay, I hope we had a short but exhaustive trip into this beautiful extension. I hope the combo of this extension with the &lt;code&gt;GitHub Pull Requests and Issues&lt;/code&gt; extension improves your daily work and I hope they could be useful for you too. If you know other&apos;s extensions or you prefer others let me know, I&apos;m curious and open to trying different extensions, especially if they improve my productivity.&lt;/p&gt;
&lt;p&gt;See you soon with other tricks for our best editor (VsCode) :)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;p.s. if you are interested in helping the VsCode team use the &lt;a href=&quot;https://code.visualstudio.com/insiders/&quot;&gt;Insider version&lt;/a&gt; and test the new features before their release. In this way, you can help the team to release a better stable version&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;p.s.s. if you want to get your hands dirty, you can also contribute to making VsCode better, by implementing new features or fixing bugs. if you are interested in that but don&apos;t know where to start, watch this &lt;a href=&quot;https://www.youtube.com/watch?v=W_xau3w4GJo&quot;&gt;video&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>github</category><category>code</category><category>actions</category></item><item><title>Working with Github from your best editor</title><link>https://delpuppo.net/blog/vs-code-tips-and-tricks/working-with-github-from-your-best-editor/</link><guid isPermaLink="true">https://delpuppo.net/blog/vs-code-tips-and-tricks/working-with-github-from-your-best-editor/</guid><description>In my daily work routine, many times I have to switch from VsCode and Github to create a PR, review a...</description><pubDate>Thu, 03 Nov 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In my daily work routine, many times I have to switch from &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VsCode&lt;/a&gt; and &lt;a href=&quot;https://github.com/&quot;&gt;Github&lt;/a&gt; to create a PR, review a PR, check a GitHub Action, and more.&lt;/p&gt;
&lt;p&gt;Therefore I have decided to google if there is a solution to prevent all these switches. The result of my search terminated with 2 new VsCode Extensions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github&quot;&gt;GitHub Pull Requests and Issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=cschleiden.vscode-github-actions&quot;&gt;GitHub Actions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Today I&apos;ll speak a bit about the first one, and the second will be discovered in another article.&lt;/p&gt;
&lt;h2&gt;GitHub Pull Requests and Issues&lt;/h2&gt;
&lt;p&gt;This extension is an official extension created by the GitHub team. This extension allows you to do whatever you want if you are working with a PR and Issues. You can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create PR&lt;/li&gt;
&lt;li&gt;Edit PR&lt;/li&gt;
&lt;li&gt;Delete PR&lt;/li&gt;
&lt;li&gt;Review PR&lt;/li&gt;
&lt;li&gt;See all PR&lt;/li&gt;
&lt;li&gt;Create Issue&lt;/li&gt;
&lt;li&gt;Delete Issue&lt;/li&gt;
&lt;li&gt;Edit Issue&lt;/li&gt;
&lt;li&gt;See all Issues&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can imagine, in our daily work if we are familiar with PRs and we work well with them, creating, editing, or reviewing PRs is a common practice.&lt;/p&gt;
&lt;p&gt;So let&apos;s see better how this extension works.&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;Obviously, to install this extension we have to pass by the VsCode MarketPlace. Click the extension button in VsCode menu and in the search bar type &quot;GitHub Pull Requests and Issues&quot;. When the search is finished, click the install button on the right, wait some seconds, and voila the extension is installed.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Login&lt;/h2&gt;
&lt;p&gt;It&apos;s going without saying that we have to sign in with our credentials to work with GitHub. To do that we have to open the extension and click the SignIn button that appears. After that VsCode asks you permission to open a new browser window to allow you to type your credentials, and at the end a popup browser asks you the permission to reopen VsCode with your credentials so you can begin to use our extensions. Now we are ready to use the extensions.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;First Impression&lt;/h2&gt;
&lt;p&gt;When you are logged the extension shows you two sections:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pull Request&lt;/li&gt;
&lt;li&gt;Issues&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;its obvious that each section handles its topic.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;PR&lt;/h3&gt;
&lt;p&gt;To create your first PR you have to click the icon in the top right of the PR section.&lt;/p&gt;
&lt;p&gt;After that, the extension opens a new window where you can input the data of your PR:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;From branch&lt;/li&gt;
&lt;li&gt;To branch&lt;/li&gt;
&lt;li&gt;Title&lt;/li&gt;
&lt;li&gt;Description&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Now, if you work using the review feature, you can add your review/s to your PR and if you want you can edit your PR too, or you can also add labels or milestones.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In the extension panel, under the PR section, you can find your PR and view or edit it if it is necessary.&lt;/p&gt;
&lt;p&gt;If you select your PR, you can see all the changed files by the PR, and if you want to add some comments you can do that in the file directly.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;It is awesome, innit?&lt;/p&gt;
&lt;p&gt;The flow for your Issues is very similar to the PR flow and in my case doing these kind of stuffs direct in my editor is very useful because Im able to handle my projects direct in VsCode without switching every time from the editor to the browser and vice-versa.&lt;/p&gt;
&lt;p&gt;Okay, I hope I stimulated your curiosity so what are you waiting for? Open your VsCode and try this fantastic extension. Let me know your impressions and if you wanna other info dont hesitate to ask me anything, you are welcome and for me its a pleasure to help you.&lt;/p&gt;
&lt;p&gt;Thats all today folks.&lt;/p&gt;
&lt;p&gt;See you soon to speak about the second extension GitHub Actions.&lt;/p&gt;
&lt;p&gt;Bye bye&lt;/p&gt;
</content:encoded><category>productivity</category><category>vscode</category><category>github</category></item><item><title>Validate your data with Zod</title><link>https://delpuppo.net/blog/validate-your-data-with-zod/</link><guid isPermaLink="true">https://delpuppo.net/blog/validate-your-data-with-zod/</guid><description>Preface Many developers don&apos;t know very well which is the line between Javascript and...</description><pubDate>Mon, 31 Oct 2022 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Preface&lt;/h2&gt;
&lt;p&gt;Many developers don&apos;t know very well which is the line between Javascript and Typescript. Probably, many of them waste much time understanding that if they write an interface like that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;interface User {
  id: number;
  username: string;
  age: number;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Typescript doesn&apos;t guarantee that the &lt;code&gt;age&lt;/code&gt; field is really a number. And probably if they have an API that returns a list of users and they have to calculate the average ages of these users, the result will not appear as expected, if the API returns the age as &lt;code&gt;string&lt;/code&gt;. This is because Typescript disappears after the build process and the type system goes away. This is one of the biggest problems that I face every day in the project where I work, especially in the frontend applications, many developers don&apos;t have the perception of this matter. Let me explain better it. First of all, I love Typescript and I work with it every day, but I also know what are its limitations. So, guaranteeing the type system at runtime is not its job, and we have to find a solution, but which is the solution? The solution is Javascript! Javascript doesn&apos;t disappear at runtime, and fortunately, it exists also at build time, therefore Javascript is our Volta key for our solution.&lt;/p&gt;
&lt;p&gt;Lets start from here: what are the most vulnerable layers in our applications when Typescript disappears? The most vulnerable layers are those that receive data from outside of the application, the ports of our applications in a nutshell. These layers must protect our application from mistakes, and they are our safety to validate and check if the data received are exactly like we aspected. To do that we have to introduce something that converts our typescript definitions to functions that can validate our data so that we are sure that the data format is what we expect.&lt;/p&gt;
&lt;p&gt;This check can be done with different libraries like: &lt;a href=&quot;https://github.com/gcanti/io-ts&quot;&gt;io-ts&lt;/a&gt;, &lt;a href=&quot;https://github.com/sinclairzx81/typebox&quot;&gt;typebox&lt;/a&gt;, or &lt;a href=&quot;https://www.npmjs.com/package/zod&quot;&gt;zod&lt;/a&gt;. These libraries allow you to create objects that represent your typescript definitions. Then, these objects can be used at runtime to validate the received data, in addition, you can also convert this object to a Typescript definition to have all the benefits of using typescript. These objects can be called &lt;code&gt;schema validations&lt;/code&gt; because they are responsible for the data validation.&lt;/p&gt;
&lt;p&gt;But stop wasting time and let&apos;s go deep into how &lt;a href=&quot;https://www.npmjs.com/package/zod&quot;&gt;zod&lt;/a&gt; works.&lt;/p&gt;
&lt;h2&gt;Zod&lt;/h2&gt;
&lt;p&gt;To use Zod, you simply have to install it using npm, yarn, pnpm. After that you have to create your first Zod type, as an example, we&apos;ll use the same type seen before, so, the User type can look like that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { z } from &quot;zod&quot;;

export const User = z.object({
  id: z.number(),
  name: z.string(),
  age: z.number(),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, we have to import Zod, and using it we can create our &lt;code&gt;validation schema&lt;/code&gt;. This new object contains the rules to validate our data at runtime. But the Zod&apos;s magic doesn&apos;t stop here. With Zod, we can also extract the relative typescript definition in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export type User = z.infer&amp;lt;typeof User&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now let&apos;s go ahead and let&apos;s see how we can use this object to validate our data. We have an API that returns a user at the endpoint &lt;code&gt;/users/1&lt;/code&gt; and the response can be&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;id&quot;: 1,
  &quot;name&quot;: &quot;Chance&quot;,
  &quot;age&quot;: 80
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, we can use the &lt;code&gt;fetch&lt;/code&gt; API to call our endpoint and the result could be something like that&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const user = await fetch(&quot;http://localhost:3001/users/1&quot;)
    .then(response =&amp;gt; response.json())
    .then(json =&amp;gt; User.parse(json));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;if you look at this code probably you won&apos;t notice anything strange but if you take a look at this screen&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;you can see how typescript is able to detect the user&apos;s type, and this is possible thanks to Zod. And to leave you another proof, if I add the type to the user variable, typescript doesn&apos;t give errors because the type is the same.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Zod exposes to us two different ways to validate our objects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;parse, parseAsync&lt;/li&gt;
&lt;li&gt;safeParse, safeParseAsync The firsts are &lt;a href=&quot;https://blog.delpuppo.net/typescript-tips-tricks-assert-function&quot;&gt;assert function&lt;/a&gt;, therefore if the validation fails the method throws an exception. Instead, the seconds return a &lt;a href=&quot;https://blog.delpuppo.net/typescript-tips-tricks-type-guard&quot;&gt;type guard&lt;/a&gt; composed like this&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;type SafeParseReturnType&amp;lt;Input, Output&amp;gt; = {
  success: true;
  data: Output;
} | {
  success: false;
  error: ZodError&amp;lt;Input&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, we have to check the &lt;code&gt;success&lt;/code&gt; field to understand if the validation is successful or failed. And if the result is positive we have a property &lt;code&gt;data&lt;/code&gt; that contains the object with the right type, otherwise, we have a property called error that contains an object with all the validation errors.&lt;/p&gt;
&lt;p&gt;At this point, let&apos;s go a little bit deepen. Now we can create a little HTTP module that helps us to be confident of the result get by the API. To do that, we can wrap the fetch API, and using the power of the generic type we can create a method like that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { z, ZodType } from &quot;zod&quot;;

export function get&amp;lt;Schema extends ZodType&amp;gt;(
  url: string,
  schema: Schema
): Promise&amp;lt;z.infer&amp;lt;Schema&amp;gt;&amp;gt; {
  return fetch(url)
    .then(response =&amp;gt; response.json())
    .then(json =&amp;gt; schema.parse(json));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and it can be used like this&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;As you can see, now using the get method we can do an HTTP get and check if the result is as expected. This is very important in our applications because by doing that we protect our application from strange mistakes and we are confident that our codebase after this layer receives the data exactly as we expected at build time. It goes without saying that if there is a bug after this layer, this is a problem of our code base and not a bug due to incongruous data.&lt;/p&gt;
&lt;p&gt;Now using this pattern we can keep alive our typescript definitions at runtime too and we can prevent mistakes relative to incongruous data. Using this pattern moreover, we can consider all the assumptions done during the development mode correct at runtime too, where typescript disappears.&lt;/p&gt;
&lt;p&gt;I know this layer can be considered too much sometimes, but I think every important application must have it. I want to leave you with this simple consideration, a time ago, a backend developer said to me: &quot;Don&apos;t trust the Frontend&quot; but now, as a Frontend developer I say to you &quot;Don&apos;t trust the Backend either&quot;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The code of that article can be found &lt;a href=&quot;https://github.com/Puppo/zod-getting-started&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>JavaScript</category><category>Web Development</category></item><item><title>Visual Studio Code - Tips &amp; Tricks - Snippets</title><link>https://delpuppo.net/blog/vs-code-tips-and-tricks/visual-studio-code-tips-tricks-snippets/</link><guid isPermaLink="true">https://delpuppo.net/blog/vs-code-tips-and-tricks/visual-studio-code-tips-tricks-snippets/</guid><description>If you used to adopt Visual Studio in the past probably you already know something about...</description><pubDate>Mon, 21 Mar 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you used to adopt Visual Studio in the past probably you already know something about Snippets.
This feature exists out-of-the-box in VsCode too.
If you open a javascript file or a typescript file and you type &lt;code&gt;log&lt;/code&gt; and after you press TAB you get this result.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In VsCode there are many others snippets already implemented out-of-the-box but the VsCode&apos;s team doesn&apos;t stop here.
VsCode enables you to create your own snippets, or import them from the extensions. But that&apos;s not all, you can create your own snippets available in all your projects, or create snippets for a specific project and accessible by all the team of that project.
After all these words, let&apos;s see how the snippets work and how you can create your own snippets.
First of all, to create a new snippet you have to open the &lt;a href=&quot;https://dev.to/this-is-learning/visual-studio-code-tips-tricks-command-palette-and-its-friends-2bhi&quot;&gt;Command Palette&lt;/a&gt;, type &quot;Configure User snippets&quot; and press ENTER. After that VsCode suggests you some options, two of these are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New Global snippets file...&lt;/li&gt;
&lt;li&gt;New Snippets file for &apos;&lt;code&gt;name of your project&lt;/code&gt;&apos;...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Chose your preference and press ENTER again, type the name of your snippet, and press ENTER for the last time. Voila, your first snippet configuration becomes reality.&lt;/p&gt;
&lt;p&gt;As you see, you can choose between two types of configuration: Global snippet and Project snippets.
It goes without saying that the first one creates a snippet file accessible only by you, the second one instead is accessible by all the project team if you commit the file in the repository.
Based on the choice, VsCode creates the snippet file in two different folders.
The global snippets are saved in this path &lt;code&gt;Code/User/snippets/{snippet-name}.code-snippets&lt;/code&gt; and the &lt;code&gt;Code&lt;/code&gt; folder is different in base of your platform:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Windows &lt;code&gt;%APPDATA%\Code\User\&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;macOS &lt;code&gt;$HOME/Library/Application\ Support/Code/User/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Linux &lt;code&gt;$HOME/.config/Code/User/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;you can find more about that configuration &lt;a href=&quot;https://code.visualstudio.com/docs/getstarted/settings#_settings-file-locations&quot;&gt;in this reference&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Instead, the project snippets are saved inside of the &lt;code&gt;.vscode&lt;/code&gt; folder in the project&apos;s root and the snippet file has this form &lt;code&gt;{snippet-name}.code-snippets&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Apart from this difference between the two choices, after the creation stream VsCode create for file for you with this content&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
	// Place your global snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and 
	// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope 
	// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is 
	// used to trigger the snippet and the body will be expanded and inserted. Possible variables are: 
	// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. 
	// Placeholders with the same ids are connected.
	// Example:
	// &quot;Print to console&quot;: {
	// 	&quot;scope&quot;: &quot;javascript,typescript&quot;,
	// 	&quot;prefix&quot;: &quot;log&quot;,
	// 	&quot;body&quot;: [
	// 		&quot;console.log(&apos;$1&apos;);&quot;,
	// 		&quot;$2&quot;
	// 	],
	// 	&quot;description&quot;: &quot;Log output to console&quot;
	// }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is an example of a snippet, particularly this example is the log snippet seen at the beginning of this article.&lt;/p&gt;
&lt;p&gt;But let&apos;s go ahead and create a snippet to generate a fetch request.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;Fetch Request&quot;: {
    &quot;scope&quot;: &quot;javascript,typescript&quot;,
    &quot;prefix&quot;: &quot;fetch&quot;,
    &quot;body&quot;: [
      &quot;fetch(\&quot;$1\&quot;)&quot;,
      &quot;	.then(response =&amp;gt; response.json())&quot;,
      &quot;	.then(data =&amp;gt; $2)&quot;,
      &quot;	.catch(error =&amp;gt; console.error(error));&quot;
    ],
    &quot;description&quot;: &quot;Fetch request&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First of all let&apos;s see this snippet at work&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;As you can tell, typing &lt;code&gt;fetch&lt;/code&gt; and pressing ENTER or TAB, VsCode inserts the code of the snippet in the file. But let&apos;s take a look at how the snippet file is composed.
First and foremost, the snippet file is a JSON file.
The first thing to do is to give a name of the snippet, in this case, &lt;code&gt;Fetch Request&lt;/code&gt; and this is the property that identifies the snippet inside of this file. By here, you have to describe your snippet.
The first property described is the &lt;code&gt;scope&lt;/code&gt;, this property identifies the language relative to this snippet, in this case, the snippet is written for javascript and typescript (if you don&apos;t indicate this property your snippet appears in all the files).
The &lt;code&gt;prefix&lt;/code&gt; property identifies the word to type to find the snippet in the VsCode&apos;s IntelliSense, &lt;code&gt;fetch&lt;/code&gt; for this example.
The description property is used to describe the reason why of the snippet.
The body property instead is the code generated by the snippet. As you can see, this property is an array, where every item is a row of the generated code. There are two &quot;strange&quot; symbols used inside of the body: $1 and $2. This particular syntax helps VsCode to understand that in this snippet the user has to indicate 2 things, the fetch&apos;s URL and the function to manipulate the fetch result. &lt;em&gt;To jump between the parameters during the filling in the editor you have to use the TAB.&lt;/em&gt;
As you can tell, it&apos;s not so difficult to create your snippets, but let&apos;s see another case to example other possibilities exposed by VsCode.
In this example, the snippet creates a React Function component with the FC type and Props.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;React Functional Component with Props&quot;: {
    &quot;scope&quot;: &quot;typescriptreact&quot;,
    &quot;prefix&quot;: &quot;rfcpt&quot;,
    &quot;body&quot;: [
      &quot;import { FC } from &apos;react&apos;&quot;,
      &quot;&quot;,
      &quot;type ${1:$TM_FILENAME_BASE}Props = {&quot;,
      &quot;  $2&quot;,
      &quot;}&quot;,
      &quot;&quot;,
      &quot;const ${1:$TM_FILENAME_BASE}: FC&amp;lt;${1:$TM_FILENAME_BASE}Props&amp;gt; = (props) =&amp;gt; {&quot;,
      &quot;  return &amp;lt;&amp;gt;$3&amp;lt;/&amp;gt;&quot;,
      &quot;}&quot;,
      &quot;&quot;,
      &quot;export default ${1:$TM_FILENAME_BASE};&quot;
    ],
    &quot;description&quot;: &quot;React.FC component with Props in TypeScript&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In this example, one parameter has a special syntax &lt;code&gt;${1:$TM_FILENAME_BASE}&lt;/code&gt;, which indicates that the first parameter will be compiled only with the name of the file when the snippet appears but the user can edit it if necessary.
There are many other special variables that you can indicate at VsCode to pre-fill a parameter and you can find all the possibilities &lt;a href=&quot;https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables&quot;&gt;in this reference&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can indicate multiple snippets inside of a single file. To do that you have to create another section in your file starting from the name and filling this section with the info about another snippet. &lt;a href=&quot;https://github.com/Puppo/vscode-tips-and-tricks/blob/02-snippets/.vscode/fetch.code-snippets&quot;&gt;in the GitHub repository&lt;/a&gt; an example.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This feature is widely used in extensions, and you can find many extensions that create for you snippets, for instance: &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=johnpapa.Angular2&quot;&gt;Angular Snippets&lt;/a&gt;, &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=dsznajder.es7-react-js-snippets&quot;&gt;ES7+ React/Redux/React-Native snippets&lt;/a&gt;...&lt;/p&gt;
&lt;p&gt;Now you know all the notions to create your snippets if it will be necessary. This feature often helps me to generate automatically the structure of some particular repeatable component in the application, for instance, a react component or an angular component or other things like these. I hope this feature can help you too to save time on writing repeatable code.&lt;/p&gt;
&lt;p&gt;That&apos;s all from the snippets guys!
Bye Bye! 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;N.B. you can find the code relatives of this article &lt;a href=&quot;https://github.com/Puppo/vscode-tips-and-tricks/tree/02-snippets&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>vscode</category><category>productivity</category><category>programming</category><category>webdev</category></item><item><title>Visual Studio Code - Tips &amp; Tricks - Command Palette and its friends</title><link>https://delpuppo.net/blog/vs-code-tips-and-tricks/visual-studio-code-tips-tricks-command-palette-and-its-friends/</link><guid isPermaLink="true">https://delpuppo.net/blog/vs-code-tips-and-tricks/visual-studio-code-tips-tricks-command-palette-and-its-friends/</guid><description>Visual Studio Code is one of the best code editors in this moment. Its Palette has many features but...</description><pubDate>Mon, 21 Feb 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Visual Studio Code is one of the best code editors in this moment.
Its Palette has many features but probably not all devs know them.
Let’s look at the most important, to improve your productivity and use less the mouse.&lt;/p&gt;
&lt;h2&gt;Command Palette&lt;/h2&gt;
&lt;p&gt;The Command Palette is the bar that shows up when you use the short-cut &lt;code&gt;⇧+⌘+P&lt;/code&gt; (on window &lt;code&gt;Ctrl+Shift+P&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;This Palette enables you to run commands. Which commands? That depends. VsCode already has many commands out-off the box, like: save file, format file, git commands and many others. But Vscode doesn&apos;t end its power here. It allows you to create new ones, and see them in this list of possibile commands. More extensions use this feature to expose their commands and enable their features.
The commands typically are grouped by topic, for instance, all the commands that work with the terminal have the prefix Terminal, those that work with git have the prefix Git and so on. This &quot;rule&quot; is a common best practice to improve the search of the commands.&lt;/p&gt;
&lt;p&gt;It&apos;s important to remember that this Palette is working with the command if its first character is &lt;code&gt;&amp;gt;&lt;/code&gt;. This char indicates you that the palette is in command mode.&lt;/p&gt;
&lt;p&gt;It goes without saying that for some commands this flow can be a bit boring, but don&apos;t worry, the VsCode team took care about that too, they allow us to create short-cuts that run your commands. But we&apos;ll see that in another post.&lt;/p&gt;
&lt;h2&gt;Search Files and Symbols&lt;/h2&gt;
&lt;p&gt;If you use the short-cut &lt;code&gt;⌘+P&lt;/code&gt; (on window &lt;code&gt;Ctrl+P&lt;/code&gt;) the Palette that appears has a different goal. In this case, it&apos;s ready to work with the files, or better, it&apos;s ready to search your files or to search inside of them.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;By default when this palette appears it is ready to work with the current opened file, but you can also work with other files.
Let&apos;s start with the commands to work in the current file.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Go to Line and Column
Using the character &lt;code&gt;:&lt;/code&gt; VsCode is ready to go to a line of the file, for example if you type :39 and you press ENTER, VsCode puts the cursor and focuses at the begin of the line 39.
If you know the column of the line, you can indicate it too by adding another &lt;code&gt;:&lt;/code&gt; and VsCode sets the focus to the column in the chosen line. For instance &lt;code&gt;:39:3&lt;/code&gt; corresponds to the line 39 at the column 3.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Search Symbols
Using the character &lt;code&gt;@&lt;/code&gt; VsCode is ready to search methods, properties, classes, interfaces inside of the current file.
As you can see, when you type the character &lt;code&gt;@&lt;/code&gt; VsCode tries to help you and it suggests you all the symbols in the file.
That helps you to search the symbols and prevent infinitive searches using the scroll.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now let&apos;s move on and see how to search files.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Search Files
The easy pease way to search a file in VsCode is using the short-cut &lt;code&gt;⌘+P&lt;/code&gt; (on window &lt;code&gt;Ctrl+P&lt;/code&gt;), type its name and press &lt;code&gt;ENTER&lt;/code&gt; when you find it. This search works on the entire project.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;But sometimes it can be necessary to search only inside of a folder.
To make this, you need to start the search with the name of the folder flow by the char &lt;code&gt;/&lt;/code&gt; and after that the name of the file.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;But this method enables the search only in the first level of this folder and excludes all the subfolders.
Thus the VsCode team took care about that too and by using the char &lt;code&gt;*&lt;/code&gt; you can create a power condition to search your files.
This char can be used either lonely or combined with another &lt;code&gt;*&lt;/code&gt;. If you use the combination, it indicates that you want search both in that folder and in its subfolders. Instead if it is used alone you indicate that the search is only inside of the folder.
Let&apos;s look at some examples to better understand this.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;/src/**/File.ts
In this case you want to search all the files called &lt;code&gt;File.ts&lt;/code&gt; inside of the folder &lt;code&gt;src&lt;/code&gt; and in its subfolders (&lt;code&gt;***&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;/src/***/components/Button.ts
In this case you want to search all the files &lt;code&gt;Button.ts&lt;/code&gt; inside of the folder &lt;code&gt;src&lt;/code&gt; that it&apos;s placed inside of a subfolder called  &lt;code&gt;components&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;/src/***&lt;em&gt;/&lt;/em&gt;.ts
In this case you want to search all the files with extension &lt;code&gt;.ts&lt;/code&gt; inside of the folder &lt;code&gt;src&lt;/code&gt; and in all its subfolder.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As you can see, combining the char &lt;code&gt;*&lt;/code&gt; in different ways you can create a power search term.&lt;/p&gt;
&lt;p&gt;I hope these notions could improve you daily work with VsCode.&lt;/p&gt;
&lt;p&gt;That&apos;s all Guys.&lt;/p&gt;
&lt;p&gt;Bye Bye 👋&lt;/p&gt;
</content:encoded><category>vscode</category><category>productivity</category><category>programming</category><category>webdev</category></item><item><title>Typescript - (ReadOnly)NotEmptyArray</title><link>https://delpuppo.net/blog/typescript-readonlynotemptyarray/</link><guid isPermaLink="true">https://delpuppo.net/blog/typescript-readonlynotemptyarray/</guid><description>Arrays are already well described in typescript, but sometimes we need to be more strict with our...</description><pubDate>Mon, 14 Feb 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Arrays are already well described in typescript, but sometimes we need to be more strict with our types. For instance, we need to have a not empty array.
This type doesn&apos;t exist in the typescript definitions, but we can create it in this way.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type NotEmptyArray&amp;lt;T&amp;gt; = [T, ...T[]];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This type inherits all the characteristics of the array type and it adds another rule to it. This array must have at least one item.
It can be used thus&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const array: NotEmptyArray&amp;lt;number&amp;gt; = [1];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you try to use it without any elements, typescript gives you an error, and it says us that a NotEmptyArray must have at least one element.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;But this type could create some problems. If you use the arrays&apos; methods that remove elements, you could have errors, because the arrays could become empty. To avoid this issue, we can work with read-only arrays that can be defined thus.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type ReadOnlyNotEmptyArray&amp;lt;T&amp;gt; = Readonly&amp;lt;NotEmptyArray&amp;lt;T&amp;gt;&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This type prevents all the arrays&apos; mutations so we can work with arrays with confidence.&lt;/p&gt;
&lt;p&gt;The last point that I want to let you is how to convert an Array to a NotEmptyArray. To do that we need to create a &lt;a href=&quot;https://dev.to/this-is-learning/typescript-tips-tricks-type-guard-50e5&quot;&gt;type guard&lt;/a&gt; function. This function can be done in this way.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function isNotEmptyArray&amp;lt;T&amp;gt;(as: T[]): as is NotEmptyArray&amp;lt;T&amp;gt; {
  return as.length &amp;gt; 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Therefore you can check if an array has at least an element and if it respects this rule it&apos;s a NotEmptyArray.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I created a &lt;a href=&quot;https://gist.github.com/Puppo/bc5287d32dbfeeba9f14862654cece9d&quot;&gt;GitHub Gist&lt;/a&gt; with this code if you need it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/Puppo/bc5287d32dbfeeba9f14862654cece9d&quot;&gt;https://gist.github.com/Puppo/bc5287d32dbfeeba9f14862654cece9d&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That&apos;s all, I hope it can be helpful in your daily work.&lt;/p&gt;
&lt;p&gt;Bye Bye Guys 👋&lt;/p&gt;
</content:encoded><category>typescript</category><category>javascript</category><category>webdev</category><category>help</category></item><item><title>It&apos;s Prisma Time - Seeding</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-seeding/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-seeding/</guid><description>Hello Folks 👋 Today we&apos;ll see how to handle seed with Prisma. Seeding allows you to re-create...</description><pubDate>Fri, 04 Feb 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello Folks 👋
Today we&apos;ll see how to handle seed with Prisma.&lt;/p&gt;
&lt;p&gt;Seeding allows you to re-create consistently the same data in your database and it can be used to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Populate your database with data that is required for your application to start - for example, a default language or a default currency.&lt;/li&gt;
&lt;li&gt;Provide basic data for validating and using your application in a development environment. This is particularly useful if you are using Prisma Migrate, which sometimes requires to reset your development database.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Prisma exposes this feature out of the box.
Creating a seed is not so difficult and now we&apos;ll see how to do it.&lt;/p&gt;
&lt;p&gt;The first step is to create a file that contains our seeds. In this case we are creating the file &lt;code&gt;index.ts&lt;/code&gt; inside of the folder &lt;code&gt;prisma/seed&lt;/code&gt;.
Now, we want that someone executes this file every time. Its code adds inside of the authors table a special author called &quot;Super Admin&quot;. The contents of this file therefore could be so&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { PrismaClient } from &quot;@prisma/client&quot;;

const run = async () =&amp;gt; {
  const prisma = new PrismaClient();
  try {
    if ((await prisma.author.count()) === 0) {
      await prisma.author.create({
        data: {
          givenName: &quot;Super&quot;,
          familyName: &quot;Admin&quot;,
          age: 100,
        },
      });
    } else {
      console.log(&quot;Default author already created&quot;);
    }
  } finally {
    await prisma.$disconnect();
  }
};

run();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, it&apos;s not so difficult to understand the code. We create a connection to the database and check if the author table is empty. If so, we add the &quot;Super Admin&quot; author.
Now we have the file and it&apos;s time to execute it.
Prisma is configurable to accept an instruction that can execute this code, and to do that we need to update our package.json file.
The configuration is easy and we can instruct prisma in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...
&quot;prisma&quot;: {
  &quot;seed&quot;: &quot;ts-node prisma/seed&quot;
},
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These three lines of code indicate to Prisma that we want to handle its seed command. When this command is executed the system uses the ts-node tool to build and execute the file &lt;code&gt;prisma/seed/index.ts&lt;/code&gt;.
But Prisma doesn&apos;t stop its work here. It executes this command after the migrate command too. Thus now we can execute this command&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma migrate dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, Prisma executes the migration and our seed file.
As a double check, we can update our &lt;code&gt;src/index.ts&lt;/code&gt; in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { PrismaClient } from &quot;@prisma/client&quot;;

async function main() {
  const prisma = new PrismaClient();
  try {
    const authors = await prisma.author.findMany();
    console.table(authors);
  } catch (error) {
    console.error(error);
    throw error;
  } finally {
    await prisma.$disconnect();
  }
}
main();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and after that run the command&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the result will seem like this&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Our database is ready with all migrations and our seeds.
Now, I think you have all the notions to work with confidence with Prisma, so it&apos;s time to let you go for your steps.
This is the last post of this &lt;a href=&quot;https://dev.to/this-is-learning/series/15827&quot;&gt;series&lt;/a&gt; folks.
I hope my posts helped you to view better this fantastic tool, surely they helped me a lot to understand it better.
So, I hope Prisma can be your friend in your daily work and it can help you to work in the right way with our databases.&lt;/p&gt;
&lt;p&gt;Before leaving you I wanted to thank the Prisma team for these fantastic swags.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;And &lt;a href=&quot;https://twitter.com/Thisis_Learning&quot;&gt;This is Learning&lt;/a&gt; for letting me publish this content in its space. I know, I could do more for you but I promise that in the next future the time to do something live will arrive too (I apologize for my bad English spoken😅). Thanks again This is Learning.&lt;/p&gt;
&lt;p&gt;Now it&apos;s really time to leave you.
I hope you&apos;ll miss this Prisma time, but now it&apos;s your prisma time. Get those keyboards ready and let&apos;s code!&lt;/p&gt;
&lt;p&gt;Bye Bye Guys 👋&lt;/p&gt;
&lt;p&gt;See you soon with new contents!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The code of this article is published &lt;a href=&quot;https://github.com/Puppo/it-s-prisma-time/tree/16-seed&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Migrations</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-migrations/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-migrations/</guid><description>Hello Guys 👋, Today it&apos;s time to speak about migrations. Migrations in Prisma are managed by Prisma...</description><pubDate>Wed, 02 Feb 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello Guys 👋,
Today it&apos;s time to speak about migrations.&lt;/p&gt;
&lt;p&gt;Migrations in Prisma are managed by &lt;em&gt;Prisma Migrate&lt;/em&gt;.
Prisma Migrate is an imperative database schema migration tool that enables you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keep your database schema in sync with your Prisma schema as it evolves and&lt;/li&gt;
&lt;li&gt;Maintain existing data in your database&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To see how it works, today we&apos;ll recreate all the schema used in this series, so let&apos;s started.&lt;/p&gt;
&lt;h2&gt;First migration&lt;/h2&gt;
&lt;p&gt;Before creating our first migration, we need to create our schema, thus in the &lt;code&gt;prisma/schema.prisma&lt;/code&gt; we will create the entities: Post, Author and AuthorsOnPost. To do that, we need to add in &lt;code&gt;prisma/schema.prisma&lt;/code&gt; this code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = &quot;prisma-client-js&quot;
}

datasource db {
  provider = &quot;sqlite&quot;
  url      = env(&quot;DATABASE_URL&quot;)
}

model Post {
  id        Int @id @default(autoincrement())
  title     String
  content   String
  published Boolean  @default(false)
  createAt  DateTime @default(now())
  updatedAt DateTime @updatedAt

  authors   AuthorsOnPost[]

  @@map(&quot;posts&quot;)
}

model Author {
  id        Int @id @default(autoincrement())
  firstName String
  lastName  String
  age       Int
  posts     AuthorsOnPost[]

  @@map(&quot;authors&quot;)
}

model AuthorsOnPost {
  author    Author @relation(fields: [authorId], references: [id])
  authorId  Int
  post      Post @relation(fields: [postId], references: [id])
  postId    Int

  @@id([authorId, postId])
  @@map(&quot;authors_on_post&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once this is done, we can generate our first migration using this command&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma migrate dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command generates our first migration for us.
If you take a look at your project, you can notice that you have a new folder called migration inside the Prisma folder. Inside this folder, there is another folder whose name is the timestamp of when you have executed the migration command. The format is YYYYmmDDhhMMss.
If you open this folder, you find a file called &lt;code&gt;migration.sql&lt;/code&gt;, where you can see inside the scripts to generate the schema of your database.
In this case, in this file, there are 3 CREATE TABLE commands, each for every entity (Author, Post, AuthorsOnPost).
Prisma allows us to indicate migration&apos;s name too by using the &lt;code&gt;--name&lt;/code&gt; option. Therefore the previous command could be executed in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma migrate dev --name create_post_and_author_entities
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By doing that, the migration&apos;s folder adds to its name this name immediately after the timestamp. Thus we have a migration with info about what it does.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Important&lt;/em&gt;
When we run the migrate command, Prisma updates our local database too.&lt;/p&gt;
&lt;h2&gt;Second migration&lt;/h2&gt;
&lt;p&gt;Now we want to add the Comment entity to our schema.
First of all we have to create it in the Prisma Schema adding this code in the &lt;code&gt;prisma/schema.prisma&lt;/code&gt; file&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;model Comment {
  id        Int @id @default(autoincrement())
  text      String
  post      Post @relation(fields: [postId], references: [id], onDelete: NoAction, onUpdate: Cascade)
  postId    Int
  author    Author? @relation(fields: [authorId], references: [id], onDelete: SetNull, onUpdate: Cascade)
  authorId  Int?

  @@map(&quot;comments&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once this is done, we need to update the entities Author and Post adding the collections of comments. To do this, you need to add these lines of code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;model Post {
  ...
  comments  Comment[]
  ...
}

model Author {
  ...
  comments  Comment[]
  ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now it&apos;s time to create our second migration using the next command&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma migrate dev --name add_comment_entity
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, now we have another folder in the migration folder that contains the last migration.&lt;/p&gt;
&lt;h2&gt;Rename a field&lt;/h2&gt;
&lt;p&gt;How we can notice, updating our schema is not so difficult using the migrate command, unless we have to rename one or more fields.
When we have to rename a field, the Prisma Migrate tool works in this way&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;CREATE a new column&lt;/li&gt;
&lt;li&gt;DROP the existing column and the data in that column&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;as you can imagine, by doing that, we&apos;ll lose our data.
But how can we handle these changes then?
To handle these changes is possible using a single migration but in different steps.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Rename the column&lt;/li&gt;
&lt;li&gt;Create the migration&lt;/li&gt;
&lt;li&gt;Edit the migration&lt;/li&gt;
&lt;li&gt;Execute the migration&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But let&apos;s see that in action.
Imagine we want to rename the field firstName and lastName of the Author entity with givenName and familyName. The first action to do is rename these fields to our schema. Then update the &lt;code&gt;prisma/schema.prisma&lt;/code&gt; in this way.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;model Author {
  ...
  givenName   String
  familyName  String
  ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After that it&apos;s time to create our migration. This time though, we&apos;ll use a special option &lt;code&gt;--create-only&lt;/code&gt;. This option allows us to create the migration script but this time the migration doesn&apos;t execute yet.
Now execute the following command&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma migrate dev --name rename_author_columns --create-only
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command generates the new migration file but now we have to edit it to avoid data loss.
If we open this file, we&apos;ll find it in this situation.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PRAGMA foreign_keys=OFF;
CREATE TABLE &quot;new_authors&quot; (
    &quot;id&quot; INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    &quot;givenName&quot; TEXT NOT NULL,
    &quot;familyName&quot; TEXT NOT NULL,
    &quot;age&quot; INTEGER NOT NULL
);
INSERT INTO &quot;new_authors&quot; (&quot;age&quot;, &quot;id&quot;) SELECT &quot;age&quot;, &quot;id&quot; FROM &quot;authors&quot;;
DROP TABLE &quot;authors&quot;;
ALTER TABLE &quot;new_authors&quot; RENAME TO &quot;authors&quot;;
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, all the data inside of the columns firstName and lastName will be lost.
To prevent this loss we need to update the insert command.
We can rewrite our insert in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;INSERT INTO &quot;new_authors&quot;
  (&quot;id&quot;, &quot;age&quot;, &quot;givenName&quot;, &quot;familyName&quot;)
SELECT
  &quot;id&quot;, &quot;age&quot;, &quot;firstName&quot;, &quot;lastName&quot;
FROM &quot;authors&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now it&apos;s time to do the last step to make this migration real&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma migrate dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By running this command our migration will be executed and our database will be updated.&lt;/p&gt;
&lt;p&gt;As you can see, Prisma Migrate is a powerful tool that can help us but if we don&apos;t pay attention we could get hurt.&lt;/p&gt;
&lt;p&gt;If you are interested in going in-depth into migrations, I let you some links about it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-migrate&quot;&gt;Prisma Migrate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-migrate#development-environments&quot;&gt;Migration in Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-migrate#production-and-testing-environments&quot;&gt;Migration in Production&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/guides/database/developing-with-prisma-migrate/customizing-migrations&quot;&gt;Customizing Migration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ok Guys, it&apos;s all for today!
In the next article we are going to speak about seeding.&lt;/p&gt;
&lt;p&gt;See you soon
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The code of this article can be find &lt;a href=&quot;https://github.com/Puppo/it-s-prisma-time/tree/15-migrations&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Execute your own queries</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-execute-your-own-queries/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-execute-your-own-queries/</guid><description>Hello Folks 👋 Today it&apos;s time to see how we can execute our own queries. In prisma we can run two...</description><pubDate>Fri, 28 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello Folks 👋
Today it&apos;s time to see how we can execute our own queries.&lt;/p&gt;
&lt;p&gt;In prisma we can run two kind of custom queries: &quot;Actionable&quot; queries (INSERT, UPDATE or DELETE) and &quot;Retrievable&quot; queries (SELECT). The first one can be executed using the &lt;code&gt;$executeRaw&lt;/code&gt; method while the other one can be executed using the &lt;code&gt;$queryRaw&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Method $executeRaw&lt;/h2&gt;
&lt;p&gt;This method enables us to create custom queries to insert update or delete records in the database.
Using the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals?retiredLocale=it#tagged_templates&quot;&gt;tagged template&lt;/a&gt; we can write our query and Prisma runs it &quot;magically&quot;.
Let’s see it in action to understand it better&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const result = await prisma.$executeRaw`
INSERT INTO posts (title, content, published, updatedAt)
VALUES (${&quot;Post Title&quot;}, ${&quot;Post Content&quot;}, ${false}, ${new Date()});`;
console.log(`Insert result: ${result}`);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, it&apos;s not so difficult to use this method.
By using the Tagged Template we can write our query and pass all the parameters in complete safety. In complete safety? Yes, you are reading right. By using this method all the parameters passed with the syntax &lt;code&gt;${parameter}&lt;/code&gt; are safe from the SQL-Injection, so we won&apos;t worry about these attacks.
&lt;em&gt;You can read more about this &lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/raw-database-access#sql-injection&quot;&gt;in this reference&lt;/a&gt;&lt;/em&gt;
The last thing that I want to leave you is the return value of this method. The method returns the number of records affected by our queries. Thus we can check if our queries are executed correctly.&lt;/p&gt;
&lt;h2&gt;Method $queryRaw&lt;/h2&gt;
&lt;p&gt;This method allows us to retrieve data using custom queries.
Sometimes, we need more performance and the query created by Prisma must be rewritten, in this case the &lt;code&gt;$queryRaw&lt;/code&gt; method is our lifeline.
This method uses the Tagged Template and it prevents attack by SQL-injection too.
The result of this method is always an array and the type of this array depends on the result of your query. To explain better this concept let me give an example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const result: Post[] = await prisma.$queryRaw&amp;lt;Post[]&amp;gt;`
SELECT p.id, p.title, p.content, p.published, p.createAt, p.updatedAt
FROM posts p
WHERE p.published = ${true}
ORDER BY p.createAt DESC`;
result.forEach(post =&amp;gt; {
  const { id, title, content, createAt, published, updatedAt } = post;
  console.log({
    id,
    title,
    content,
    createAt,
    published,
    updatedAt,
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you look closely this piece of code, you can notice that the &lt;code&gt;result&lt;/code&gt; variable is an array of type Post, and also the &lt;code&gt;$queryRaw&lt;/code&gt; method indicates that as its return type. By doing so, we receive the right check by typescript in the following rows of code. But there is a thing to keep in mind. The conversion from the result of the query to your type is not guaranteed by Prisma, it&apos;s your business in this case.
&lt;em&gt;N.B. If you don&apos;t indicate your result type, by default Prisma returns the &lt;a href=&quot;https://dev.to/this-is-learning/typescript-tips-tricks-any-vs-unknown-2ho6&quot;&gt;unknown&lt;/a&gt; type&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s move on and see another feature that we can adopt when we are using these methods.
Sometimes we have to use the IN operator in a custom query. Probably you are thinking that using the &lt;code&gt;map&lt;/code&gt; method of the array is the right thing, unfortunately it&apos;s not so. To do this, Prisma exposes us a specific method &lt;code&gt;Prisma.join&lt;/code&gt;. This method builds for us the IN clause in a safety mode, so we can use it in our custom queries.
Let&apos;s see it in action&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const posts = await prisma.$queryRaw&amp;lt;
  Post[]
&amp;gt;`SELECT * FROM posts WHERE id IN (${Prisma.join([1, 2, 3])})`;
console.log(`Posts in 1,2,3: ${JSON.stringify(posts, null, 2)}`);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, in this piece of code the values in the IN clause are built using the &lt;code&gt;join&lt;/code&gt; method, nothing so difficult but it&apos;s important to keep in mind to use it in these cases.&lt;/p&gt;
&lt;p&gt;Two other good features exposed by Prisma are the &lt;code&gt;Prisma.sql&lt;/code&gt; and &lt;code&gt;Prisma.empty&lt;/code&gt;. These features enable us to create dynamic queries. Imagine that your query needs to do a WHERE clause only if there is a filter. By combining these two features you can create a custom query that depends on the data that you receive. Let&apos;s see an example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const author: string | undefined = &quot;transaction&quot;;
const authors = await prisma.$queryRaw&amp;lt;Author[]&amp;gt;`
SELECT * FROM authors a ${
  !!author
    ? Prisma.sql`WHERE a.firstName || &apos; &apos; || a.lastName LIKE ${`%${author}%`}`
    : Prisma.empty
}`;

console.log(`Authors: ${JSON.stringify(authors, null, 2)}`);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, in this example we check the value of the author variable, and if it&apos;s defined the query will execute using the filter (Prisma.sql), otherwise the query will execute without the filter(Prisma.empty).
Even here, nothing so difficult to understand but these are two really good methods to write our own queries better.&lt;/p&gt;
&lt;p&gt;Ok Guys, it&apos;s all for today.
In the next article we are going to see how to use the migrations with Prisma.&lt;/p&gt;
&lt;p&gt;See you soon
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this article &lt;a href=&quot;https://github.com/Puppo/it-s-prisma-time/tree/14-execute-your-queries&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Logging</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-logging/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-logging/</guid><description>Hi Guys 👋 Today we are going to see how to enable logging in Prisma, so don&apos;t waste time and let&apos;s...</description><pubDate>Wed, 26 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Guys 👋
Today we are going to see how to enable logging in Prisma, so don&apos;t waste time and let&apos;s start!&lt;/p&gt;
&lt;p&gt;In Prisma we have 4 type of logging&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;query: this level of log allows us to see the queries created by Prisma to perform our operations&lt;/li&gt;
&lt;li&gt;info&lt;/li&gt;
&lt;li&gt;warn&lt;/li&gt;
&lt;li&gt;error&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;I think the last three levels of log don’t need a description if you’re a developer.&lt;/em&gt;
We can enable all of them or only those are necessary.
By default these logs are written in the stdout, but we can also send them in an event and handle them as we prefer.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;P.S. if you are in development mode, you can enable all of these log levels setting the DEBUG environment variable to true&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;But let&apos;s see how to enable these logs.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const prisma = new PrismaClient({
    log: [
      {
        emit: &quot;event&quot;,
        level: &quot;query&quot;,
      },
      &quot;info&quot;,
      &quot;warn&quot;,
      &quot;error&quot;,
    ],
  });
  prisma.$on(&quot;query&quot;, e =&amp;gt; {
    console.log(&quot;Query: &quot; + e.query);
    console.log(&quot;Duration: &quot; + e.duration + &quot;ms&quot;);
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The log option accepts an array of log levels that can be simple strings (query, info, warn, or error) or objects composed of two fields: level and emit. The level field can have query, info, warn, or error as values; whereas the emit field can have two values: stdout or event. If the &quot;emit&quot; value is equal to &quot;stdout&quot;, the result of this log level will be written in the console, otherwise, if the value is &quot;event&quot;, the result must be handled by a subscriber.
But let’s clarify and see how to manage these logs.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const prisma = new PrismaClient({
  log: [
    {
      emit: &quot;event&quot;,
      level: &quot;query&quot;,
    },
    &quot;info&quot;,
    &quot;warn&quot;,
    &quot;error&quot;,
  ],
});
prisma.$on(&quot;query&quot;, e =&amp;gt; {
  console.log(&quot;Query: &quot; + e.query);
  console.log(&quot;Duration: &quot; + e.duration + &quot;ms&quot;);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this snippet of code, you can see how to enable the log levels and how to handle a subscriber of a specific type of log level.
As you can see, it&apos;s not difficult to enable logs but it&apos;s important to remember to do it in the right way in base of the environment where our software is running.
It&apos;s also possibile, as you can tell, to subscribe to the events of a log using the &lt;code&gt;$on&lt;/code&gt; method. By using this method you can send where you want all your logs.
The last thing that I want to leave you is an example of a query logged in the console.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT `main`.`posts`.`id`, `main`.`posts`.`title`, `main`.`posts`.`content`, `main`.`posts`.`published`, `main`.`posts`.`createAt`, `main`.`posts`.`updatedAt` FROM `main`.`posts` WHERE `main`.`posts`.`published` = ? LIMIT ? OFFSET ?
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, you can get the real SQL query executed by Prisma, and you can copy and past it in other SQL tool to check its plan or everything else.
In this way, we can check if we have a slowdown and if we need to write our own query.
The How is the goal of the next article 😁&lt;/p&gt;
&lt;p&gt;So that&apos;s all for now folks. In the next article, we are going to see how to execute own queries using Prisma.&lt;/p&gt;
&lt;p&gt;See you soon guys
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this article &lt;a href=&quot;https://github.com/puppo/it-s-prisma-time/tree/13-logging-query&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Transactions</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-transactions/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-transactions/</guid><description>Hello Guys 👋 Today it&apos;s time to speak about transactions. Transactions are a pillar of the database...</description><pubDate>Thu, 20 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello Guys 👋
Today it&apos;s time to speak about transactions.&lt;/p&gt;
&lt;p&gt;Transactions are a pillar of the database world, and they help us to make consistency in the data when we work with multiple entities.
So, can Prisma not handle them?
Obviously the answer is no 😃&lt;/p&gt;
&lt;p&gt;In this moment, Prisma handles the transactions in two ways, the first one is the official feature and the second one is in preview.
Let&apos;s start from the first one.
The first method to do a transaction in Prisma is using the &lt;code&gt;$transaction&lt;/code&gt; method. This method accepts a list of operations that are performed in a single transaction.
If all of these operations are successful the transaction does the commit otherwise it does the rollback.
Let&apos;s see this method at work.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const result = await prisma.$transaction([
  prisma.author.create({
    data: {
      firstName: &quot;Author from transaction&quot;,
      lastName: &quot;Author from transaction&quot;,
      age: getRandomInt(16, 100),
    },
  }),
  prisma.post.create({
    data: {
      title: &quot;Post from transaction&quot;,
      content: &quot;Post from transaction&quot;,
      published: false,
    },
  }),
]);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result of this operation is an array of elements, where the elements are the result of each operation in the transaction, in our example the result is composed in this way &lt;code&gt;[Author, Post]&lt;/code&gt;.
As you can imagine, this type of transaction is a good solution if you need to create a bulk insert or if you need to create a list of entities not relative to each other.
Therefore, to solve this problem, the Prisma team is working to improve the transaction method.
In this time, we can try this feature in preview, enabling it in the &lt;code&gt;schema.prisma&lt;/code&gt; file.
First of all, open the &lt;code&gt;schema.prisma&lt;/code&gt; file and update the generator client in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;generator client {
  provider = &quot;prisma-client-js&quot;
  previewFeatures = [&quot;interactiveTransactions&quot;]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;N.B. since &lt;a href=&quot;https://github.com/prisma/prisma/releases/tag/4.7.0&quot;&gt;4.7.0&lt;/a&gt;, this feature has been production ready, so you can remove the &lt;code&gt;&quot;interactiveTransactions&quot;&lt;/code&gt; flag.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;after that it&apos;s necessary to update the prisma definitions, so run in your terminal this command&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma generate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By doing this, we enabled the feature.
Now, we&apos;ll see the previous example, rewritten in the way that the author and post are in relation.
Let&apos;s see the result&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const result = await prisma.$transaction(async prisma =&amp;gt; {
  const authorData = {
    firstName: &quot;Author from transaction&quot;,
    lastName: &quot;Author from transaction&quot;,
    age: getRandomInt(16, 100),
  } as const;
  const author = await prisma.author.create({
    data: authorData,
  });
  const post = await prisma.post.create({
    data: {
      title: &quot;Post from transaction&quot;,
      content: &quot;Post from transaction&quot;,
      published: false,
      authors: {
        create: [
          {
            authorId: author.id,
          },
        ],
      },
    },
    include: {
      authors: {
        include: {
          author: true,
        },
      },
    },
  });
  return { author, post };
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, this feature allows us to handle the transaction like a function, and in this function we can do all the operations that we want to guarantee under transaction. We can also create an entity by using the create method and await its result. After that we can use this result to create or update another entity always under transaction.
If you want to roll back the transaction because there are some inconsistent data, you need to throw an exception.&lt;/p&gt;
&lt;p&gt;I think for today that&apos;s all, but before I let you go, I suggest you this &lt;a href=&quot;https://www.prisma.io/docs/guides/performance-and-optimization/prisma-client-transactions-guide&quot;&gt;reading&lt;/a&gt; about transactions in the prisma site. It explains very well how this feature works and how to handle it in the best way.&lt;/p&gt;
&lt;p&gt;In the next article, we are going to see how to log the queries executed by Prisma, but now it&apos;s time to say goodbye 😃&lt;/p&gt;
&lt;p&gt;See you soon Guys
Bye bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this article &lt;a href=&quot;https://github.com/puppo/it-s-prisma-time/tree/12-transaction&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Aggregate and GroupBy</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-aggregate-and-groupby/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-aggregate-and-groupby/</guid><description>Welcome back Folks 👋 Today we are seeing how to aggregate and group data. Let&apos;s start from the...</description><pubDate>Tue, 18 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome back Folks 👋
Today we are seeing how to aggregate and group data.&lt;/p&gt;
&lt;p&gt;Let&apos;s start from the first one.
To aggregate data in Prisma you have to use the &lt;a href=&quot;https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#aggregate&quot;&gt;aggregate&lt;/a&gt; method.
Using this method, you can aggregate data of type number, and you can do these operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;max&lt;/li&gt;
&lt;li&gt;min&lt;/li&gt;
&lt;li&gt;count&lt;/li&gt;
&lt;li&gt;sum&lt;/li&gt;
&lt;li&gt;avg&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;N.B. I won&apos;t spend time explaining what these operations do because I think their names speak for themselves&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Therefore, let&apos;s give an example to see the aggregate method at work.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const aggregate = await prisma.author.aggregate({
  _avg: {
    age: true,
  },
  _max: {
    age: true,
  },
  _min: {
    age: true,
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, in this example, we aggregated the authors and we got as result the authors&apos; ages average, the age of the older author and the age of the younger author. The result is composed in this way:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
    _avg: {
        age: true;
    };
    _max: {
        age: true;
    };
    _min: {
        age: true;
    };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In addition, the aggregate method allows us to use these operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;where&lt;/li&gt;
&lt;li&gt;orderBy&lt;/li&gt;
&lt;li&gt;take&lt;/li&gt;
&lt;li&gt;skip&lt;/li&gt;
&lt;li&gt;cursor&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So as you can immagine, you can filter and sort your data before aggregate them.
I think this feature might be clear that way, so let&apos;s move on to the groupBy feature.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#groupby&quot;&gt;groupBy&lt;/a&gt; feature allows us to group data by one o more fields.
Let’s see an example to start&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const commentsGroupByPost = await prisma.comment.groupBy({
  by: [&quot;postId&quot;],
  _count: {
    authorId: true,
    _all: true,
  },
  orderBy: {
    _count: {
      authorId: &quot;desc&quot;,
    },
  },
  having: {
    authorId: {
      _count: {
        gt: 1,
      },
    },
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, we grouped the comments by post, and after that, we counted the number of comments with the author and the number of comments for that post.
Moreover, we sorted the result by the authors&apos; count and, using the having option, we took only the posts that have at least a comment with an author.
As you can see, this method is not difficult to use and understand. &lt;em&gt;It&apos;s also possibile to filter the data with the &lt;code&gt;where&lt;/code&gt; option.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I think for today that&apos;s all.
We saw how to aggregate and how to group data using Prisma and, if you want to deepen, the prisma team created this &lt;a href=&quot;https://www.youtube.com/watch?v=BdlCPdPaorY&quot;&gt;video&lt;/a&gt; to explain better the groupBy feature.&lt;/p&gt;
&lt;p&gt;In the next article we will see how to run our queries under transaction, but for today it&apos;s time to close 😃&lt;/p&gt;
&lt;p&gt;See you soon guys
Bye bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To show the code of this article in action follow this &lt;a href=&quot;https://github.com/puppo/it-s-prisma-time/tree/11-grouping-and-aggregate&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Pagination</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-pagination/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-pagination/</guid><description>Hi Guys 👋 Today we are going to see how to paginate our results. So don&apos;t waste time and let&apos;s...</description><pubDate>Thu, 13 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Guys 👋
Today we are going to see how to paginate our results.
So don&apos;t waste time and let&apos;s go!&lt;/p&gt;
&lt;p&gt;With Prisma there are two ways to paginate results: &lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/pagination#offset-pagination&quot;&gt;Offset pagination&lt;/a&gt; or &lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination&quot;&gt;Cursor-based pagination&lt;/a&gt;.
What are the differences though?
The first one is used when we need to create a sequence of pages and get their datas according to the page. The second one, instead, is used when we want the items after a specific record, to continue the list after that element.&lt;/p&gt;
&lt;p&gt;But let&apos;s see an example of both, starting with the first one &lt;code&gt;skip&lt;/code&gt; and &lt;code&gt;take&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  const pageOnePosts = await prisma.post.findMany({
    take: 3,
    orderBy: {
      id: &quot;asc&quot;,
    },
  });
  console.log(`Page 1: `, JSON.stringify(pageOnePosts, undefined, 2));

  const pageTwoPosts = await prisma.post.findMany({
    skip: 3,
    take: 3,
    orderBy: {
      id: &quot;asc&quot;,
    },
  });
  console.log(`Page 2: `, JSON.stringify(pageTwoPosts, undefined, 2));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result of this example is this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[
  {
    &quot;id&quot;: 1,
    &quot;title&quot;: &quot;Post title 1&quot;,
    &quot;content&quot;: &quot;Post content 1&quot;,
    &quot;published&quot;: false,
    &quot;createAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;
  },
  {
    &quot;id&quot;: 2,
    &quot;title&quot;: &quot;Post title 8&quot;,
    &quot;content&quot;: &quot;Post content 8&quot;,
    &quot;published&quot;: true,
    &quot;createAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;
  },
  {
    &quot;id&quot;: 3,
    &quot;title&quot;: &quot;Post title 4&quot;,
    &quot;content&quot;: &quot;Post content 4&quot;,
    &quot;published&quot;: true,
    &quot;createAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;
  }
]

[
  {
    &quot;id&quot;: 4,
    &quot;title&quot;: &quot;Post title 10&quot;,
    &quot;content&quot;: &quot;Post content 10&quot;,
    &quot;published&quot;: true,
    &quot;createAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;
  },
  {
    &quot;id&quot;: 5,
    &quot;title&quot;: &quot;Post title 9&quot;,
    &quot;content&quot;: &quot;Post content 9&quot;,
    &quot;published&quot;: false,
    &quot;createAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;
  },
  {
    &quot;id&quot;: 6,
    &quot;title&quot;: &quot;Post title 6&quot;,
    &quot;content&quot;: &quot;Post content 6&quot;,
    &quot;published&quot;: true,
    &quot;createAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;
  }
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the first &lt;code&gt;findMany&lt;/code&gt; has the orderBy and the take options. The orderBy is used to give a sort to our results and the take option is used to get the first 3 elements of the results. In this case the skip option isn&apos;t indicated so its value is 0 (default value). Instead, in the second &lt;code&gt;findMany&lt;/code&gt; method there is also the skip option, and it&apos;s indicated with the value 3. In this case, the findMany method returns 3 elements (take: 3) after the third element (skip: 3), so we can see the results of the second page.
I think it&apos;s not so difficult to understand it, so let&apos;s go on to the cursor implementation.
Let&apos;s start from the code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const pageOnePosts = await prisma.post.findMany({
  take: 3,
  orderBy: {
    id: &quot;asc&quot;,
  },
});
console.log(`Page 1: `, JSON.stringify(pageOnePosts, undefined, 2));

const pageTwoPosts = await prisma.post.findMany({
  skip: 1,
  take: 3,
  cursor: {
    id: pageOnePosts[pageOnePosts.length - 1].id,
  },
  orderBy: {
    id: &quot;asc&quot;,
  },
});
console.log(`Page 2: `, JSON.stringify(pageTwoPosts, undefined, 2));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The results&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[
  {
    &quot;id&quot;: 1,
    &quot;title&quot;: &quot;Post title 1&quot;,
    &quot;content&quot;: &quot;Post content 1&quot;,
    &quot;published&quot;: false,
    &quot;createAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;
  },
  {
    &quot;id&quot;: 2,
    &quot;title&quot;: &quot;Post title 8&quot;,
    &quot;content&quot;: &quot;Post content 8&quot;,
    &quot;published&quot;: true,
    &quot;createAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;
  },
  {
    &quot;id&quot;: 3,
    &quot;title&quot;: &quot;Post title 4&quot;,
    &quot;content&quot;: &quot;Post content 4&quot;,
    &quot;published&quot;: true,
    &quot;createAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;
  }
]

[
  {
    &quot;id&quot;: 4,
    &quot;title&quot;: &quot;Post title 10&quot;,
    &quot;content&quot;: &quot;Post content 10&quot;,
    &quot;published&quot;: true,
    &quot;createAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;
  },
  {
    &quot;id&quot;: 5,
    &quot;title&quot;: &quot;Post title 9&quot;,
    &quot;content&quot;: &quot;Post content 9&quot;,
    &quot;published&quot;: false,
    &quot;createAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;
  },
  {
    &quot;id&quot;: 6,
    &quot;title&quot;: &quot;Post title 6&quot;,
    &quot;content&quot;: &quot;Post content 6&quot;,
    &quot;published&quot;: true,
    &quot;createAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T10:14:51.274Z&quot;
  }
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you may notice, the results are the same of the previous example but the implementation is a little bit different in the second part.
In this case, the second findMany has the same orderBy and take options as in the first example, but it has a different skip and uses the cursor option. First let&apos;s focus on the cursor option. This option allows us to indicate the last item returns by the previous search, so we can restart our pagination from this element and combining it with the &lt;code&gt;skip: 1&lt;/code&gt;, we&apos;ll get the results after this element.
&lt;em&gt;It&apos;s important to indicate the skip option with the one value, otherwise the element indicates in the cursor is part of the results.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As you can tell, both implementations are correct but each of them resolve a different type of pagination. Now it&apos;s your job to take the right one.&lt;/p&gt;
&lt;p&gt;Ok guys that&apos;s all!
I hope now you have an idea of how you can paginate your datas using prisma.
In the next article, we are going to see how to aggregate and group the datas.&lt;/p&gt;
&lt;p&gt;See you soon!
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://github.com/Puppo/it-s-prisma-time/tree/10-pagination&quot;&gt;in the GitHub repository&lt;/a&gt; you can find the code of this article.&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Select</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-select/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-select/</guid><description>Welcome back Guys, Today it&apos;s time to get our record using the select command. Let&apos;s start with a...</description><pubDate>Tue, 11 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome back Guys,
Today it&apos;s time to get our record using the select command.&lt;/p&gt;
&lt;p&gt;Let&apos;s start with a simple example (copy and paste the setup method in the &lt;a&gt;repository&lt;/a&gt; if you want some record in your database).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const prisma = new PrismaClient();
const posts = await prisma.post.findMany();
console.log(JSON.stringify(posts, undefined, 2));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, to do the select in Prisma we need to use the &lt;a href=&quot;https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#findmany&quot;&gt;findMany&lt;/a&gt; method. In this case, the code does a simple select without anything else (no where, no groupBy, no orderBy...), it&apos;s like doing this query&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SELECT *
FROM POSTS
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But let&apos;s move on and add a WHERE clause to our select.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...
const posts = await prisma.post.findMany({
  where: {
    id: {
      gte: 5,
    },
  },
});
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The where clause is the same seen in the previous articles (delete and update), so I won&apos;t go in depth because I&apos;ve already spent many words about it.
Therefore let&apos;s see the order by command&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const posts = await prisma.post.findMany({
  orderBy: {
    published: &quot;desc&quot;,
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the orderBy command is so simple, you need to create an object and indicate the column used for the sorting and its direction (&quot;desc&quot; or &quot;asc&quot;). But if you want to indicate multiple columns in your sorting, the syntax is a little bit different. Let&apos;s see it in this code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const posts = await prisma.post.findMany({
  orderBy: [{ published: &quot;desc&quot; }, { createAt: &quot;asc&quot; }],
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can tell, when you need to indicate multiple columns, the orderBy field wants an array of values, and each value must contains the column name and its direction.&lt;/p&gt;
&lt;p&gt;But let&apos;s go on and see how to indicate only a subset of columns of our entity.
Supposing that we want to select only the fields &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt; of the Post Entity, how can we do that?
Fortunately, in the findMany method there is a configuration to indicate that, let&apos;s see it the next code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const posts = await prisma.post.findMany({
  select: {
    id: true,
    title: true,
    content: true,
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, using the select option, we can indicate the column we want to extract, but Prisma doesn&apos;t end here its works. When we use the select option, Prisma returns an object that respects our selection, so the typescript compiler can detect the right fields of the objects. In this case the &lt;code&gt;posts&lt;/code&gt; collection has this type&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const posts: {
    id: number;
    title: string;
    content: string;
}[]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&apos;s fantastic I think, isn&apos;t it?&lt;/p&gt;
&lt;p&gt;Ok let&apos;s go on and see the &lt;code&gt;include&lt;/code&gt; option.
The include option is used to load the relative Entities too.
Immagine you want get for each post its relative authors and its comments; using the include option it&apos;s possibile.
Let&apos;s see how in the next code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const posts = await prisma.post.findMany({
  include: {
    authors: {
      select: {
        author: true,
      },
    },
    comments: true,
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the include option allows us to get the authors and the comments relative to each post.
The result of this query is&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[
  {
    &quot;id&quot;: 1,
    &quot;title&quot;: &quot;Post title 2&quot;,
    &quot;content&quot;: &quot;Post content 2&quot;,
    &quot;published&quot;: true,
    &quot;createAt&quot;: &quot;2022-01-03T08:52:30.690Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T08:52:30.690Z&quot;,
    &quot;authors&quot;: [
      {
        &quot;author&quot;: {
          &quot;id&quot;: 4,
          &quot;firstName&quot;: &quot;First name 2&quot;,
          &quot;lastName&quot;: &quot;Last name 2&quot;
        }
      }
    ],
    &quot;comments&quot;: []
  },
  {
    &quot;id&quot;: 2,
    &quot;title&quot;: &quot;Post title 5&quot;,
    &quot;content&quot;: &quot;Post content 5&quot;,
    &quot;published&quot;: false,
    &quot;createAt&quot;: &quot;2022-01-03T08:52:30.690Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T08:52:30.690Z&quot;,
    &quot;authors&quot;: [
      {
        &quot;author&quot;: {
          &quot;id&quot;: 3,
          &quot;firstName&quot;: &quot;First name 5&quot;,
          &quot;lastName&quot;: &quot;Last name 5&quot;
        }
      }
    ],
    &quot;comments&quot;: []
  },
  {
    &quot;id&quot;: 3,
    &quot;title&quot;: &quot;Post title 1&quot;,
    &quot;content&quot;: &quot;Post content 1&quot;,
    &quot;published&quot;: false,
    &quot;createAt&quot;: &quot;2022-01-03T08:52:30.690Z&quot;,
    &quot;updatedAt&quot;: &quot;2022-01-03T08:52:30.690Z&quot;,
    &quot;authors&quot;: [
      {
        &quot;author&quot;: {
          &quot;id&quot;: 5,
          &quot;firstName&quot;: &quot;First name 1&quot;,
          &quot;lastName&quot;: &quot;Last name 1&quot;
        }
      }
    ],
    &quot;comments&quot;: []
  }
  ...
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After the explanation of the &lt;code&gt;findMany&lt;/code&gt; method, it&apos;s important to spend some words about other two methods: &lt;a href=&quot;https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#findunique&quot;&gt;findUnique&lt;/a&gt; and &lt;a href=&quot;https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#findfirst&quot;&gt;findFirst&lt;/a&gt;. As you can immagine, these two methods allow us to retrieve a single record. The findFirst is like the findMany but it returns the first record of the result. The findUnique otherwise returns a record by its key. If they do not find any results return &lt;code&gt;null&lt;/code&gt;.
Let&apos;s see an example of both:
&lt;em&gt;- findFirst&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const post = await prisma.post.findFirst({
  where: {
    published: true,
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;_- findUnique&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const post = await prisma.post.findUnique({
  where: {
    id: 1,
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok, I think that&apos;s all for today.
In the next article we are going to see how to paginate the results.&lt;/p&gt;
&lt;p&gt;See you soon guys!
Bye Bye!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://github.com/Puppo/it-s-prisma-time/tree/09-select&quot;&gt;in the GitHub repository&lt;/a&gt; you can find the code of this article&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Update</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-update/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-update/</guid><description>Hi Folks 👋 Today it&apos;s time to learn something about the update operation, so don&apos;t waste time and...</description><pubDate>Fri, 07 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Folks 👋
Today it&apos;s time to learn something about the update operation, so don&apos;t waste time and let&apos;s go!&lt;/p&gt;
&lt;p&gt;The update method in Prisma is not that different from the insert. Let&apos;s give an example.
Starting from the code of the previous article, you can remove all the code relative to the delete operation and after the insert you can add the following code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const updatedAuthor = await prisma.author.update({
  data: {
    firstName: &quot;Updated first name&quot;,
    lastName: &quot;Updated last name&quot;,
  },
  where: {
    id: authors[0].id,
  },
});
console.log({ updatedAuthor });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the update method used the patter &lt;code&gt;prisma.[entity].update&lt;/code&gt;, not so different from the insert and the delete, obviously the update method updates an existing row. And another thing, if the update method doesn&apos;t find the record, it throws an exception that you have to handle in your code.
If you execute that code you get this result.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  updatedAuthor: {
    id: 3,
    firstName: &apos;Updated first name&apos;,
    lastName: &apos;Updated last name&apos;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think this operation is easy to understand, but now let me show you some special features that the update method exposes.
In some cases, when we want to update a row, we don&apos;t want to set a new value, but we want to &lt;code&gt;increment&lt;/code&gt;, &lt;code&gt;decrement&lt;/code&gt;, &lt;code&gt;multiply&lt;/code&gt; or &lt;code&gt;divide&lt;/code&gt; a field in a &lt;a href=&quot;https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#atomic-number-operations&quot;&gt;atomic update operation&lt;/a&gt;. To do this Prisma exposes us these commands in the type &lt;code&gt;IntFieldUpdateOperationsInput&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export type IntFieldUpdateOperationsInput = {
  set?: number
  increment?: number
  decrement?: number
  multiply?: number
  divide?: number
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and we can use it in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const updatedAuthor = await prisma.author.update({
  data: {
    id: {
      increment: 1
    }
  },
  where: {
    id: authors[0].id,
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Obviously, incrementing the primary key doesn&apos;t have sense, but this is just a demonstrative example.
Let&apos;s go on and see another important feature exposed by the update operation, to work with the relative collections.
In the insert operation, we saw that when we want to insert a new record, we can use &lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#create-a-related-record&quot;&gt;create&lt;/a&gt;, &lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#connect-an-existing-record&quot;&gt;connect&lt;/a&gt; or &lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#connect-or-create-a-record&quot;&gt;connectOrCreate&lt;/a&gt; operation to create a relation between two records. In the update operation in addition we have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#update-or-create-a-related-record&quot;&gt;upsert&lt;/a&gt;: update or create a related record&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#disconnect-all-related-records&quot;&gt;set&lt;/a&gt;: connect the record with an existing records, &lt;em&gt;(if you set this field with an empty you disconnect all record)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#disconnect-a-related-record&quot;&gt;disconnect&lt;/a&gt;: remove the relation with existing records&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#delete-specific-related-records&quot;&gt;delete&lt;/a&gt;: delete the record in relation with it&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#update-a-specific-related-record&quot;&gt;update&lt;/a&gt;: update the related record&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#update-all-related-records-or-filter&quot;&gt;updateMany&lt;/a&gt;: update the related records&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#delete-all-related-records&quot;&gt;deleteMany&lt;/a&gt;: delete the related records&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I let you the official document for each type, so you can deepen if you are interested.&lt;/p&gt;
&lt;p&gt;As you can imagine, over the update operation there is the updateMany operation. In this article I prefer not to look into this operation because I have already left you many info about the update. But let me spend some words about it, so you can try it by yourself.
The updateMany operation combine the &lt;code&gt;where&lt;/code&gt; seen in the deleteMany operation with the features explained above, so it&apos;s obvious to understand that this operation allows you to update many records, using a complex filter.&lt;/p&gt;
&lt;p&gt;It&apos;s all for today guys.
In the next article it&apos;s time to see the select operation.&lt;/p&gt;
&lt;p&gt;See you soon
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this article &lt;a href=&quot;https://github.com/Puppo/it-s-prisma-time/tree/08-update&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Delete</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-delete/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-delete/</guid><description>Hi Guys 👋 today we are going to see the delete operation. Before moving to the delete operation, in...</description><pubDate>Wed, 05 Jan 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Guys 👋
today we are going to see the delete operation.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Before moving to the delete operation, in the code of this article I added the next snippet of code at the beginning, so every time you run the code you have some records in your database.&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const authors = await Promise.all(
  [1, 2, 3].map(
    async i =&amp;gt;
      await prisma.author.create({
        data: {
          firstName: `First name ${i}`,
          lastName: `Last name ${i}`,
        },
      })
  )
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The delete operation in Prisma can be done in two ways: the deletion of one record and the deletion of multiple records.
Let&apos;s start from the first one and let&apos;s see the next code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const deletedAuthor = await prisma.author.delete({
  where: {
    id: authors[0].id,
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the delete method is quite simple, you need to follow this pattern &lt;code&gt;prisma.[entity].delete&lt;/code&gt;, the where field must have the primary key of the record that has to be deleted.
It&apos;s important to remember that if this method doesn&apos;t find a record to delete, throws an Exception that you can handle in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;try {
  const deletedAuthor = await prisma.author.delete({
    where: {
      id: 1,
    },
  });
  console.log({ deletedAuthor });
} catch (error) {
  if (
    error instanceof Prisma.PrismaClientKnownRequestError &amp;amp;&amp;amp;
    error.code === &quot;P2025&quot;
  ) {
    console.log(&quot;Author not found&quot;);
  } else console.error(error);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;If you are interested in seeing all the possibile errors returned by Prisma you can find the documentation &lt;a href=&quot;https://www.prisma.io/docs/reference/api-reference/error-reference&quot;&gt;in this reference&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s bring the delete to the next level and let&apos;s see the deleteMany method.
I think you already have understood that this method allows you to delete multiple records in one step, but let me show you an example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const deletedAuthorsResult = await prisma.author.deleteMany({
  where: {
    id: {
      in: authors.map(a =&amp;gt; a.id),
    }
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, this method isn&apos;t so different from the delete, but the differences are in the where field and in this method you can filter the datas like in a SQL where.
In this particular case the code deletes the records that have the id contained in the array passed by the authors collection.
Another difference between the deleteMany and the delete is the result&apos;s type. The deleteMany returns an object with a single property called &lt;code&gt;count&lt;/code&gt; and it contains the amount of the records effected by the delete operation.&lt;/p&gt;
&lt;p&gt;Now, I would spend some words about the &quot;where&quot; because it exposes a lot of possibilities to search the records that we want to delete.
Thus I want to start this explanation from the &quot;author where&quot;&apos;s typescript definition.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export type AuthorWhereInput = {
  id?: IntFilter | number
  firstName?: StringFilter | string
  lastName?: StringFilter | string
  comments?: CommentListRelationFilter
  posts?: AuthorsOnPostListRelationFilter
  AND?: Enumerable&amp;lt;AuthorWhereInput&amp;gt;
  OR?: Enumerable&amp;lt;AuthorWhereInput&amp;gt;
  NOT?: Enumerable&amp;lt;AuthorWhereInput&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, this type has some strange things, but if you are familiar with the SQL, I think you have an idea of what you can do.
Don&apos;t waste time and let&apos;s start from the &lt;code&gt;id&lt;/code&gt;.
The id field can have two values, either a number or &lt;code&gt;IntFilter&lt;/code&gt;. At this point, if you need to find your record using the id, you can pass your value to this field, else if you want to delete records using more complex search terms you can use the &lt;code&gt;IntFilter&lt;/code&gt;, which is composed thus&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export type IntFilter = {
  equals?: number
  in?: Enumerable&amp;lt;number&amp;gt;
  notIn?: Enumerable&amp;lt;number&amp;gt;
  lt?: number
  lte?: number
  gt?: number
  gte?: number
  not?: NestedIntFilter | number
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can image this type represents the common operations that you can do in SQL with the numbers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;equals: checks if the value is equal to the passed value&lt;/li&gt;
&lt;li&gt;in: checks if the value is inside of the list of numbers that you pass&lt;/li&gt;
&lt;li&gt;notIn: is the opposite of &lt;code&gt;in&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;lt: checks if the value is less than the passed value&lt;/li&gt;
&lt;li&gt;lte: checks if the value is less or equal to the passed value&lt;/li&gt;
&lt;li&gt;gt: checks if the value is greater than the passed value&lt;/li&gt;
&lt;li&gt;gte: checks if the value is greater or equal to the passed value&lt;/li&gt;
&lt;li&gt;not: checks if a value is not of the passed value, or you can also set it with the type &lt;code&gt;NestedIntFilter&lt;/code&gt;, which is another type equal to the &lt;code&gt;IntFilter&lt;/code&gt;, and it allows you to create your filters using the positive search terms and check if the records respect the opposite.
As you may imagine, there are other three types similar to: StringFilter, BoolFilter and DateTimeFilter, and each one depends from the column&apos;s type that you are testing.
DateTimeFilter is equal to the IntFilter expect that works
with the Date. BoolFilter contains only the &lt;code&gt;equals&lt;/code&gt; and the &lt;code&gt;not&lt;/code&gt; operations for obvious reasons. The StringFilter in addition to the operations exposed by the IntFilter has other three operations: &lt;code&gt;contains&lt;/code&gt;, &lt;code&gt;startsWith&lt;/code&gt; and &lt;code&gt;endsWith&lt;/code&gt; (I won&apos;t describe these operations because I think they speak by themselves).
After this explanation, I think you have understood also the fields: &lt;code&gt;firstName&lt;/code&gt;, &lt;code&gt;lastName&lt;/code&gt;.
Now I want to go on to the &lt;code&gt;posts&lt;/code&gt; and &lt;code&gt;comments&lt;/code&gt; fields, that have the same approach.
These fields allow you to check some particular cases inside the posts or the comments related to the record. Each field allows you to do these three operations &lt;code&gt;every&lt;/code&gt;, &lt;code&gt;some&lt;/code&gt; and &lt;code&gt;none&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;export type CommentListRelationFilter = {
  every?: CommentWhereInput
  some?: CommentWhereInput
  none?: CommentWhereInput
}

export type AuthorsOnPostListRelationFilter = {
  every?: AuthorsOnPostWhereInput
  some?: AuthorsOnPostWhereInput
  none?: AuthorsOnPostWhereInput
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using these filters you can check inside of the posts or the comments relative to the Author, so you can check:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if &lt;code&gt;every&lt;/code&gt; post/comment has a particular value or more particular values&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;some&lt;/code&gt; post/comment has a particular value or more particular values&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;none&lt;/code&gt; post/comment has a particular value or more particular values
It&apos;s not so difficult to understand it but I recommend you to play with them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now it&apos;s time to see the last three operations: &lt;code&gt;AND&lt;/code&gt;, &lt;code&gt;OR&lt;/code&gt; and &lt;code&gt;NOT&lt;/code&gt;.
I think you already understood their goals, but let me spend some words.
These three operations let you to combine multiple filters using the operation AND OR NOT. You can combine together these operations and you can also nest them. For instance, you can use the AND and the OR in the first level of your filter, and use the NOT and the OR inside the AND filter.
I think an example can give the idea.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const deletedAuthorsResult = await prisma.author.deleteMany({
  where: {
    AND: [
      {
        NOT: {
          id: 10,
        },
      },
      {
        OR: {
          firstName: {
            startsWith: &quot;name&quot;,
          },
        },
      },
    ],
    OR: [
      {
        posts: {
          every: {
            post: {
              updatedAt: {
                lt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 7),
              },
            },
          },
        },
      },
    ],
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, you can do every type of check in you delete using the &lt;code&gt;deleteMany&lt;/code&gt; and I think the definition types created by the Prisma team are a good friends to prevent errors. It&apos;s obvious that they don&apos;t create the right query for you, that&apos;s your work. 💪&lt;/p&gt;
&lt;p&gt;That&apos;s all for today guys!
I hope I let you a good introduction about the delete in prisma and that now you are ready to go to try it by yourself.
In the next article it&apos;s time to speak about the update operation, so see you soon folks!&lt;/p&gt;
&lt;p&gt;Bye Bye! 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The code of this article is available &lt;a href=&quot;https://github.com/Puppo/it-s-prisma-time/tree/07-delete&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Insert</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-insert/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-insert/</guid><description>Welcome Guys, Today it&apos;s time to add some records to the database 😁 so don&apos;t waste time and get your...</description><pubDate>Thu, 30 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome Guys,
Today it&apos;s time to add some records to the database 😁 so don&apos;t waste time and get your hand dirty.&lt;/p&gt;
&lt;p&gt;Let&apos;s start from a simple insert that adds an author, in your &lt;code&gt;src/index.ts&lt;/code&gt; copy the next example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { PrismaClient } from &quot;@prisma/client&quot;;

async function main() {
  const prisma = new PrismaClient();
  try {
    const newAuthor = await prisma.author.create({
      data: {
        firstName: &quot;John&quot;,
        lastName: &quot;Doe&quot;,
      },
    });
    console.log({ newAuthor });
  } catch (error) {
    console.error(error);
    throw error;
  } finally {
    await prisma.$disconnect();
  }
}

main();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this code you created a simple insert that adds an author.
By using the patter &lt;code&gt;prisma.[entity].create&lt;/code&gt; you can insert in your db your entities, but let&apos;s see this code in action executing the next two script&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma db push
yarn dev
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;{ newAuthor: { id: 1, firstName: &apos;John&apos;, lastName: &apos;Doe&apos; } }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see it&apos;s not so hard to insert a record, but it&apos;s time to take the insert to the next level.
Imagine that you want to insert a Post with one Comment in a single execution, how can you do that?
Well, add to the previous code the next one, below the &lt;code&gt;console.log({ newAuthor });&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...
const newPost = await prisma.post.create({
  data: {
    title: &quot;First Post&quot;,
    content: &quot;This is the first post&quot;,
    published: false,
    comments: {
      create: {
        text: &quot;First comment&quot;,
        author: {
          connect: {
            id: newAuthor.id,
          },
        },
      },
    },
  },
  include: {
    comments: true,
  },
});

console.log(&quot;newPost&quot;, JSON.stringify(newPost, null, 4));
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And now run the code using&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma db push
yarn dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;after that you can see this result&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;newPost {
    &quot;id&quot;: 7,
    &quot;title&quot;: &quot;First Post&quot;,
    &quot;content&quot;: &quot;This is the first post&quot;,
    &quot;published&quot;: false,
    &quot;createAt&quot;: &quot;2021-12-18T12:29:20.982Z&quot;,
    &quot;updatedAt&quot;: &quot;2021-12-18T12:29:20.982Z&quot;,
    &quot;comments&quot;: [
        {
            &quot;id&quot;: 7,
            &quot;text&quot;: &quot;First comment&quot;,
            &quot;postId&quot;: 7,
            &quot;authorId&quot;: 7
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But what happened?
By running this code you added in you database a post and a comment related to this post using a single command. I think you agree with me that it is a common feature in an ORM. But let&apos;s see better the create method and its parameters.
Let&apos;s start from the &lt;code&gt;data&lt;/code&gt; field, this field allows you to indicate all the fields related to your entity, in this case the Post Entity. When I say the entity&apos;s fields I am referring to the own fields but also to the fields of its related Entities as you did with the Comment Entity in the previous example.
But let&apos;s move on and see another particularity in this example. To add the comment related to your post you used this snippet of code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...
comments: {
  create: {
    text: &quot;First comment&quot;,
    author: {
      connect: {
        id: newAuthor.id,
      },
    },
  },
},
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first thing that comes to our attention is the create field. This field is not a field of the Comment Entity but is a command for Prisma. Using the &lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#create-a-related-record&quot;&gt;create&lt;/a&gt; command you are indicating to Prisma that you want to insert a new record in the comment table. The data relative to the comment are indicated inside of the create object just described. Okay but let’s look into this object where there is another peculiarity inside the field author. As you can see inside it there is a field called &lt;code&gt;connect&lt;/code&gt;, but what is it? The &lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#connect-an-existing-record&quot;&gt;connect&lt;/a&gt; field is another command for Prisma. This command indicates to Prisma that the Author&apos;s record already exists in the database and it must not create it but it only needs to create the link between the comment record and the author record.
There is another command for Prisma to manage the insert of an entities and it is &lt;code&gt;connectOrCreate&lt;/code&gt;. This command allows us to check if the relative record exists and in this case Prisma creates the link between the entities, otherwise if it doesn&apos;t exist Prisma creates also this new record. To give you an example, here, the author connect command rewrites with the &lt;code&gt;connectOrCreate&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;author: {
  connectOrCreate: {
    create: {
      lastName: &quot;Last name&quot;,
      firstName: &quot;First name&quot;,
    },
    where: {
      id: newAuthor.id,
    },
  },
},
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When you insert a new record, all the crud operations in your database are made under a transaction, so if in your insertion you have an entity with 3 sub-entities, you&apos;ll get the success result only if all operations will be successful, otherwise you&apos;ll get an error and your database will be left clean as before the execution.&lt;/p&gt;
&lt;p&gt;There is also a &lt;code&gt;createMany&lt;/code&gt; method that allows you to do a bulk insert inside a collection. It isn&apos;t so different from the &lt;code&gt;create&lt;/code&gt; method. I leave you the link to the documentation &lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/crud#create-multiple-records&quot;&gt;in this reference&lt;/a&gt;.
&lt;em&gt;N.B. createMany isn&apos;t supported in SQLite, Prisma helps you on that and when generates the definitions of the client, it detects the current connector and generates only the definitions supported by the connector&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Last but not least, Prisma exposes you a specific type for typescript that describes how you can call the create method in a type safe context. Next the author insert reviews with this type&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Prisma, PrismaClient } from &quot;@prisma/client&quot;;

...
const authorCreate: Prisma.AuthorCreateArgs = {
      data: {
        firstName: &quot;John&quot;,
        lastName: &quot;Doe&quot;,
      },
    };

    const newAuthor = await prisma.author.create(authorCreate);
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Prisma does this work for all the entities that you described in the &lt;code&gt;prisma.schema&lt;/code&gt; file and it doesn&apos;t just make this, but we will go deep into this in the next articles.&lt;/p&gt;
&lt;p&gt;I think today you have got many notions about the insert with prisma. If you are interested in go in depth on the insert with prisma &lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client/crud#create&quot;&gt;in this reference&lt;/a&gt; the link to the official documentation.&lt;/p&gt;
&lt;p&gt;That’s it guys.
In the next article we’re going to see the delete operation.&lt;/p&gt;
&lt;p&gt;See you soon.
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this article &lt;a href=&quot;https://github.com/Puppo/it-s-prisma-time/tree/06-insert&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Create Relations</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-create-relations/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-create-relations/</guid><description>Hi Folks 👋 today I&apos;ll show you how to create relations among your entities. So don&apos;t waste time and...</description><pubDate>Tue, 28 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Folks 👋
today I&apos;ll show you how to create relations among your entities. So don&apos;t waste time and let&apos;s start!&lt;/p&gt;
&lt;p&gt;Before moving on, let me explain what we are going to do today.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a relation 1-N among posts and comments&lt;/li&gt;
&lt;li&gt;Create a relation N-N among posts and authors&lt;/li&gt;
&lt;li&gt;Explain a relation 1-1&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So get started from the first one.&lt;/p&gt;
&lt;h2&gt;1-N&lt;/h2&gt;
&lt;p&gt;To create the relation among Posts and Comments see the next code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;model Post {
  ...
  comments  Comment[]
}

model Comment {
  id        Int @id @default(autoincrement())
  text      String
  post      Post @relation(fields: [postId], references: [id], onDelete: NoAction, onUpdate: Cascade)
  postId    Int
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see in this example there are 3 steps&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Creation of the comment entity&lt;/li&gt;
&lt;li&gt;Creation of the relation between Post and Comment (&lt;code&gt;@relation&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Addition of the comments collection in the Post entity&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&apos;s focus on the second point now&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;post      Post @relation(fields: [postId], references: [id], onDelete: NoAction, onUpdate: Cascade)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;this line of code says Prisma that in Comment entity there is a field &lt;code&gt;postId&lt;/code&gt; related to the field &lt;code&gt;id&lt;/code&gt; in &lt;code&gt;Post&lt;/code&gt; entity. In this way you described the relation between Post and Comment entities. It&apos;s also possibile to describe what to do when a foreign key is deleted or updated using the keyword &lt;code&gt;onDelete&lt;/code&gt; and &lt;code&gt;onUpdate&lt;/code&gt;. This two commands could have 5 possibile values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-schema/relations/referential-actions#cascade&quot;&gt;Cascade&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-schema/relations/referential-actions#noaction&quot;&gt;NoAction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-schema/relations/referential-actions#restrict&quot;&gt;Restrict&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-schema/relations/referential-actions#setdefault&quot;&gt;SetDefault&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-schema/relations/referential-actions#setnull&quot;&gt;SetNull&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not all of them are guaranteed in all the databases connector, but you can find &lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-schema/relations/referential-actions#types-of-referential-actions&quot;&gt;in this reference&lt;/a&gt; all the info about that.
Let&apos;s move on to the third point where you added this line of code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;comments  Comment[]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;this line create a collection of comments inside the Post Entity like in every ORM that respects itself, so you can retrive by code the comments related to your post.&lt;/p&gt;
&lt;p&gt;But let&apos;s move on and see the next relation.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;N.B. it&apos;s possible to create a not mandatory foreign key too. In our context it makes no sense, but imagine that a comment should exist also without a Post. In order to map this relation you need to change the Comment entity in this way&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;model Comment {
  ...
  post      Post? @relation(fields: [postId], references: [id])
  postId    Int?
  ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Using the &lt;code&gt;?&lt;/code&gt; character, you should indicate to Prisma that the field can be null.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;N-N&lt;/h2&gt;
&lt;p&gt;See the following code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;model Post {
  id        Int @id @default(autoincrement())
  title     String
  content   String
  published Boolean
  comments  Comment[]
  authors   AuthorsOnPost[]
}

model Author {
  id        Int @id @default(autoincrement())
  firstName String
  lastName  String
  comments  Comment[]
  posts     AuthorsOnPost[]
}

model AuthorsOnPost {
  author    Author @relation(fields: [authorId], references: [id])
  authorId  Int
  post      Post @relation(fields: [postId], references: [id])
  postId    Int

  @@id([authorId, postId])
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see there are 5 steps&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Creation of the Author entity&lt;/li&gt;
&lt;li&gt;Creation of the AuthorsOnPost entity&lt;/li&gt;
&lt;li&gt;Creation of the relation between Posts and Authors using the AuthorsOnPost entity&lt;/li&gt;
&lt;li&gt;Adding the collection of AuthorsOnPost in the Post Entity&lt;/li&gt;
&lt;li&gt;Adding the collection of AuthorsOnPost in the Authors Entity
Let&apos;s start to see the second point where you created a new Entity with two fields: &lt;code&gt;authorId&lt;/code&gt; and &lt;code&gt;postId&lt;/code&gt;.
&lt;code&gt;authorId&lt;/code&gt; is a foreign key related to the Author Entity whereas &lt;code&gt;postId&lt;/code&gt; is a foreign key related to the Post Entity, I think if you understood the previous paragraph, you don&apos;t have any problem to understand this. Using the &lt;code&gt;@@id&lt;/code&gt; you indicated to prisma that the AuthorsOnPost had a primary key composed by this two fields, so you can have the same author and the same post only once. By doing that, you have created a relation N-N between Authors and Posts, so in your database now, you can have a Post with multiple Authors and an Author can contribute to multiple Posts.
The last two steps instead allow you to have the collection of Authors related to a Post and viceversa.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;1-1&lt;/h2&gt;
&lt;p&gt;For this particular relation I hope you have understood the syntax so I&apos;ll leave a symbolic example. We can say that you have a Post that can be in relation only with an Author and viceversa, you have to describe that relation like this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;model Post {
  ...
  author    Author @relation(fields: [authorId], references: [id])
  authorId  Int
}

model Author {
  .....
  post      Post?
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think it&apos;s not so hard to understand what I explained before, but it was necessary to bring this example too.&lt;/p&gt;
&lt;p&gt;I think that&apos;s everything from the Relation&apos;s world with Prisma, but before updating the database, let me add to the project a package that creates the ER diagram of your database.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install the package &lt;code&gt;prisma-erd-generator&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;yarn add -D prisma-erd-generator
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;update the &lt;code&gt;prisma/schema.prisma&lt;/code&gt; with the following code&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;generator client {
  provider = &quot;prisma-client-js&quot;
}

generator erd {
  provider = &quot;prisma-erd-generator&quot;
}

...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now when you call the script &lt;code&gt;npx prisma generate&lt;/code&gt;, Prisma generates for you also a file &lt;code&gt;prisma/ERD.svg&lt;/code&gt; where you can see your ER Diagram.&lt;/p&gt;
&lt;p&gt;Now it&apos;s time to upgrade your database and your types, so execute the next two scripts in your terminal&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma generate
npx prisma db push
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now your db is up to date and you have a new file like the next where there is your ER Diagram.
&lt;/p&gt;
&lt;p&gt;That&apos;s all for today guys, in the next article it&apos;s time to see how you can insert data in you table.&lt;/p&gt;
&lt;p&gt;Before the greetings, if you are interested in seeing the prisma-erd-generator package you can find the repository &lt;a href=&quot;https://github.com/keonik/prisma-erd-generator&quot;&gt;in the GitHub repository&lt;/a&gt; and if you want to leave a ⭐, press the button 😉&lt;/p&gt;
&lt;p&gt;Ok, see you soon Guys
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The code relatives to this article is available &lt;a href=&quot;https://github.com/Puppo/it-s-prisma-time/tree/05-create-relations&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Create Db</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-create-db/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-create-db/</guid><description>Hi Guys 👋 welcome back. Finally, today it&apos;s time to create our database, so don&apos;t waste time, and get...</description><pubDate>Thu, 23 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Guys 👋
welcome back.
Finally, today it&apos;s time to create our database, so don&apos;t waste time, and get started.
How can you create your database?
It&apos;s simple! You have to run the following script:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma db push
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This script creates in your &lt;code&gt;prisma&lt;/code&gt; folder a SQLite database called &lt;code&gt;dev.db&lt;/code&gt;.
The database&apos;s name is taken from the variable &lt;code&gt;DATABASE_URL&lt;/code&gt; in the &lt;code&gt;.env&lt;/code&gt; file and inside of the file you can find the next table.

Ok, now you have your database so it&apos;s time to get back at the challenge left open last article.
Run the script&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yarn dev
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;{ posts: [] }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Ok, there aren&apos;t data but it works 🥳
So now you have a database and you can search data inside it, at this point, it&apos;s time to create relations between our entities, but it&apos;s the goal of the next article 🤪&lt;/p&gt;
&lt;p&gt;That&apos;s all for today guys!
See you soon
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code relative to this post &lt;a href=&quot;https://github.com/Puppo/it-s-prisma-time/tree/04-create-db&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Create Table</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-create-table/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-create-table/</guid><description>Hello Folks 👋 and welcome back to this series, today it&apos;s time to create your first table with...</description><pubDate>Tue, 21 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello Folks 👋  and welcome back to this series,
today it&apos;s time to create your first table with prisma, are you ready? Then let&apos;s go 💪&lt;/p&gt;
&lt;p&gt;Before starting, let me explain which type of tables we are going to create in this series. For this series we are going to create a simple db to manage a blog, ok.. not a big and strong blog but an easy blog to focus our learn on the main concepts of prisma. Since we’re talking about blogs, let&apos;s start from the post table obviously.
Open the &lt;code&gt;prisma/schema.prisma&lt;/code&gt; file and append the following snippet.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;model Post {
  id        Int @id @default(autoincrement())
  title     String
  content   String
  published Boolean  @default(false)
  createAt  DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@map(&quot;posts&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Great! But what did you do adding this code? 🤔
Writing this code you described the entity Post and you indicated to Prisma:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I want an entity called Post&lt;/li&gt;
&lt;li&gt;This entity has 6 properties&lt;/li&gt;
&lt;li&gt;The id property is of type Integer, it is the primary key of my entity (&lt;code&gt;@id&lt;/code&gt;) and it must be auto-generated (&lt;code&gt;@default(autoincrement())&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The title property is of type String&lt;/li&gt;
&lt;li&gt;The content property is of type String&lt;/li&gt;
&lt;li&gt;The published property is of type Boolean and its default value is false&lt;/li&gt;
&lt;li&gt;The createAt is of type DateTime and when a new record is inserted, set it with the current date time&lt;/li&gt;
&lt;li&gt;The updatedAt is of type DateTime and when a record is updated, update it with the current date time (&lt;code&gt;@updatedAt&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Call the table &quot;posts&quot; (&lt;code&gt;@@map(&quot;posts&quot;)&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Well, nothing so difficult, just some special syntax to remember.
I don&apos;t want to go too deep but If you are interested in the Data model of Prisma &lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-schema/data-model#defining-models&quot;&gt;in this reference&lt;/a&gt; the link to the documentation.
&lt;em&gt;N.B. It&apos;s important to know well the mapping between the Prisma&apos;s types and the native&apos;s types of the different database services&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;But let&apos;s go ahead, you described your entity now I think you want use it.
To use this entity inside of your typescript code, you need to create its typescript definition. To do this, run the following code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma generate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command adds in you package.json a new dependence &lt;code&gt;@prisma/client&lt;/code&gt;, and creates a folder &lt;code&gt;.prisma&lt;/code&gt; inside of your node_modules folder.
The &lt;code&gt;@prisma/client&lt;/code&gt; is the package that contains the client to connect to your database, whereas, the .prisma folder contains a file &lt;code&gt;index.d.ts&lt;/code&gt; that describes the post Entity and all the possible functions to work with this Entity.
Ok, at this point, let&apos;s try to get data from this collection of &lt;code&gt;posts&lt;/code&gt; and to do this let&apos;s create a file called &lt;code&gt;index.ts&lt;/code&gt; inside the src folder and copy the following code. (&lt;code&gt;src/index.ts&lt;/code&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { PrismaClient } from &quot;@prisma/client&quot;;

async function main() {
  const prisma = new PrismaClient();
  try {
    const posts = await prisma.post.findMany();
    console.log({ posts });
  } finally {
    prisma.$disconnect();
  }
}

main();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this simple code, you created a connection to your database, found the posts inside the posts collections, and logged the result in the console.
To run this code you have to add this section in your &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...
  &quot;scripts&quot;: {
    &quot;dev&quot;: &quot;ts-node ./src/index.ts&quot;
  },
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This script permits you to run the code written above.
Ok, it&apos;s time to show the result. Run in your terminal the following script.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yarn dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
Ok, maybe that&apos;s not the result that you expected but something&apos;s gone 😅
The error that you are seeing in your terminal appeared because we haven&apos;t a database.... we haven&apos;t a database yet 😃
In the next article, I&apos;ll show you how to create the database and we&apos;ll resolve this terrible mistake, I promise!&lt;/p&gt;
&lt;p&gt;I think that could be all for today!
See you soon Guys
Bye Bye 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The code of this article is available &lt;a href=&quot;https://github.com/Puppo/it-s-prisma-time/tree/03-create-table&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Setup</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-setup/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-setup/</guid><description>Hi Guys, welcome to the second article of this series. Today I&apos;ll show you how to setup a project...</description><pubDate>Thu, 16 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Guys,
welcome to the second article of this series.&lt;/p&gt;
&lt;p&gt;Today I&apos;ll show you how to setup a project with Prisma.
This project in addition to prisma uses typescript, but let&apos;s start.&lt;/p&gt;
&lt;p&gt;The first thing that you need to do is to initialize a folder as a node project. To do this you need to run the following command in your terminal. (I used yarn but if you prefer npm or something else feel free to use it)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yarn init -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I suppose that if you are here you know what you did running this command.
We go on and add now to our workspace some dependencies using the next command.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yarn add -d typescript @types/node ts-node prisma
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first three dependencies are related to typescript and they are necessary to use typescript in our project, the last one is the &lt;a href=&quot;https://www.prisma.io/docs/reference/api-reference/command-reference&quot;&gt;Prisma CLI&lt;/a&gt;. The Prisma CLI helps us to create, update or view our database, it is easy to use and it hasn&apos;t a lot of commands to remember.
Now it&apos;s time to create our Prisma schema, for this series I decided to use SQLite as database service because it&apos;s the easiest to set up. Run the following command to generate the schema.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx prisma init --datasource-provider sqlite
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, this command created a file &lt;code&gt;schema.prisma&lt;/code&gt; inside of the folder &lt;code&gt;prisma&lt;/code&gt;.
In this file, you can see two sections: client and db.
The client section is used to identify the provider used to manage the connection with the source, whereas in the db section you can find the connection string to the database and the provider to identify the type of the source, in our case &lt;code&gt;SQLite&lt;/code&gt;.
The schema file is the single source of truth when we use Prisma, in this file, we add all the entities and all their relations. From this file, Prisma can generate our typescript types related to the entities and it can create our migration scripts to upgrade the schema of our source.
As you can see, the schema file needs to access an environment variable(DATABASE_URL), so to do this, it was created a file &lt;code&gt;.env&lt;/code&gt; in the root of the project where inside we can find this variable.&lt;/p&gt;
&lt;p&gt;The last thing I want to leave you today is related to the parameter &lt;code&gt;--datasource-provider&lt;/code&gt; in the script. By default, if you don&apos;t pass this parameter the script uses PostgreSQL as database service, so if you need to use a different service you need to specify it using the &lt;code&gt;--datasource-provider&lt;/code&gt; parameter.&lt;/p&gt;
&lt;p&gt;I think this is all for today. In the next article we are going to create our first table with Prisma and we are going to start playing with this tool.&lt;/p&gt;
&lt;p&gt;Ok guys, see you soon 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this article &lt;a href=&quot;https://github.com/Puppo/it-s-prisma-time/tree/02-setup&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>It&apos;s Prisma Time - Introduction</title><link>https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-introduction/</link><guid isPermaLink="true">https://delpuppo.net/blog/it-s-prisma-time/its-prisma-time-introduction/</guid><description>Hi Folks 👋 and welcome back, Today I want to start a new series about Prisma. But before starting I...</description><pubDate>Tue, 14 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Folks 👋 and welcome back,
Today I want to start a new series about &lt;a href=&quot;https://www.prisma.io/&quot;&gt;Prisma&lt;/a&gt;.
But before starting I want to explain the reason why of this series.
In the last months I spent more time using &lt;a href=&quot;https://it.wikipedia.org/wiki/Object-relational_mapping&quot;&gt;ORM&lt;/a&gt; in the node eco-system. Most of the time I used &lt;a href=&quot;https://typeorm.io/&quot;&gt;typeorm&lt;/a&gt;. In my opinion Typeorm is a great ORM but creates entities and managing them sometimes it&apos;s not so easy, especially if you love to use &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;typescript&lt;/a&gt; without classes. But one day in my twitter&apos;s wall appeared this &lt;a href=&quot;https://twitter.com/matteocollina/status/1384900740754386946?s=20&quot;&gt;tweet&lt;/a&gt; of &lt;a href=&quot;https://twitter.com/matteocollina&quot;&gt;@Matteo Collina&lt;/a&gt; that spoke about &lt;a href=&quot;https://www.prisma.io/&quot;&gt;prisma&lt;/a&gt;, so I decided to spend some of my free time to understand better this tool.

As you can imagine, it left me good impressions so I decide to share them with you using this series.&lt;/p&gt;
&lt;h2&gt;What&apos;s in this series?&lt;/h2&gt;
&lt;p&gt;In this series, I&apos;m going to show you how to set up a project with Prisma and how it can work in your codebase. I&apos;m going to try to create shot articles with only one goal for each article, to permit you to understand better the goal and don&apos;t switch context during the reading.&lt;/p&gt;
&lt;h2&gt;What&apos;s not in this series?&lt;/h2&gt;
&lt;p&gt;In this series I am not going to show you how to create a repository to split the data access layer with the business logic layer or how to structure your project to have a clean code, that&apos;s not the goal of the series, and I know that already exist many books and articles that speak about it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A little preamble: I don&apos;t love so much using ORM in my code, but sometimes they help the team to increase its velocity. Despite everything, it&apos;s important to check the queries generated by the ORM because sometimes they aren&apos;t optimized. In these cases, it&apos;s a good solution writing your query in order to improve the velocity of its execution.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s start with an introduction of &lt;strong&gt;Prisma&lt;/strong&gt;.
In this article I picked some infos about Prisma from its site. This helps you to have an idea of what it is and which are they goals.&lt;/p&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Prisma is an open source next-generation ORM. It consists of the following parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-client&quot;&gt;Prisma Client&lt;/a&gt;: Auto-generated and type-safe query builder for Node.js &amp;amp; TypeScript&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-migrate&quot;&gt;Prisma Migrate&lt;/a&gt;: Migration system&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.prisma.io/docs/concepts/components/prisma-studio&quot;&gt;Prisma Studio&lt;/a&gt;: GUI to view and edit data in your database&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;It&apos;s important to remember that if you prefer using javascript without typescript, you can choose this way without any problem because Prisma guarantees both solutions.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Prisma Goals&lt;/h2&gt;
&lt;p&gt;Prisma&apos;s main goal is to make application developers more productive when working with databases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Thinking in objects&lt;/strong&gt; instead of mapping relational data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Queries not classes&lt;/strong&gt; to avoid complex model objects&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Single source of truth&lt;/strong&gt; for database and application models&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Healthy constraints&lt;/strong&gt; that prevent common pitfalls and antipatterns&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;An abstraction that makes the right thing easy&lt;/strong&gt; (&quot;pit of success&quot;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type-safe database queries&lt;/strong&gt; that can be validated at compile time&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Less boilerplate&lt;/strong&gt; so developers can focus on the important parts of their app&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auto-completion in code editors&lt;/strong&gt; instead of needing to look up documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Prisma Connectors&lt;/h2&gt;
&lt;p&gt;Prima allow us to connect to the major SQL and NOSQL services.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;MySql&lt;/li&gt;
&lt;li&gt;SQLite&lt;/li&gt;
&lt;li&gt;MongoDB&lt;/li&gt;
&lt;li&gt;Microsoft SQL Server&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think that as an introduction of the tool and to give you an idea about it, it may be all. If you are curious and you want to go deep inside about Prisma, in its &lt;a href=&quot;https://www.prisma.io/docs/concepts/overview&quot;&gt;documentation&lt;/a&gt; you can find more info.&lt;/p&gt;
&lt;p&gt;I think for today it&apos;s all, but before ending this article, I wish to thank Prisma for the cover of this series, the original image is hosted in the &lt;a href=&quot;https://www.facebook.com/prisma.io/&quot;&gt;Prisma facebook account&lt;/a&gt; at this &lt;a href=&quot;https://www.facebook.com/prisma.io/photos/a.1593544297636616/2378801429110895/?type=1&amp;amp;theater&quot;&gt;in this reference&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So see you in the next article where we&apos;ll start to setup our project.
Bye bye 👋&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>database</category><category>orm</category></item><item><title>RxJS - Marble Testing</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-marble-testing/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-marble-testing/</guid><description>Hello Folks 👋! Today it&apos;s time to speak about testing and how to test the code when we use...</description><pubDate>Fri, 08 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello Folks 👋!
Today it&apos;s time to speak about testing and how to test the code when we use RxJS.
Before moving our focus to the testing, I need to explain two different types of Observables: cold and hot.&lt;/p&gt;
&lt;h2&gt;Hot and Cold&lt;/h2&gt;
&lt;p&gt;When you create an Observable, you can create a hot or a cold observable. This characteristic depends on where the producer of this Observable is set; when the producer is created by the Observable, the observable is &quot;cold&quot;, instead when the producer is created out from the observable it is defined &quot;hot&quot;.
Let me shed some light on all these words.
&lt;strong&gt;What&apos;s a producer?&lt;/strong&gt;
The producer is the source of the values of our observable.
&lt;strong&gt;Cold Observables&lt;/strong&gt;
Cold Observables are functions that create the producer and manage it for all its life. The cold observable is in charge of these things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;create the producer&lt;/li&gt;
&lt;li&gt;activate the producer&lt;/li&gt;
&lt;li&gt;start listening to the producer&lt;/li&gt;
&lt;li&gt;unicast&lt;/li&gt;
&lt;li&gt;close the producer&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&apos;s an example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const source = new Observable((observer) =&amp;gt; {
  const socket = new WebSocket(&apos;ws://someurl&apos;);
  socket.addEventListener(&apos;message&apos;, (e) =&amp;gt; observer.next(e));
  return () =&amp;gt; socket.close();
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Hot Observables&lt;/strong&gt;
An observable is “hot” if its underlying producer is either created or activated outside of subscription.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;shares a reference to a producer&lt;/li&gt;
&lt;li&gt;starts listening to the producer&lt;/li&gt;
&lt;li&gt;multicast (usually)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&apos;s an example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const socket = new WebSocket(&apos;ws://someurl&apos;);
const source = new Observable((observer) =&amp;gt; {
  socket.addEventListener(&apos;message&apos;, (e) =&amp;gt; observer.next(e));
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok, I think that now you have an idea of the difference between these two types and I can move to the topic of the day, but if you are interested in deepen this argument &lt;a href=&quot;https://benlesh.medium.com/hot-vs-cold-observables-f8094ed53339&quot;&gt;in this reference&lt;/a&gt; is a post about Hot and Cold written by &lt;a href=&quot;https://twitter.com/BenLesh&quot;&gt;Ben Lesh&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Marble Testing&lt;/h2&gt;
&lt;p&gt;To test our code in RxJS we use Marble testing. A method that combines the &lt;a href=&quot;https://dev.to/this-is-learning/rxjs-marble-diagrams-4jmg&quot;&gt;Marble Diagram&lt;/a&gt; with the code, and allows us to represent the behaviours of our observables and translate them to something that the Testing Framework can understand.&lt;/p&gt;
&lt;h3&gt;Marble Syntax&lt;/h3&gt;
&lt;p&gt;As you can imagine, the marble testing has its own syntax to represent the behaviours and here you can find its rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt; &lt;/code&gt; whitespace: horizontal whitespace is ignored, and can be used to help vertically align multiple marble diagrams.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-&lt;/code&gt; frame: 1 &quot;frame&quot; of virtual time passing (see above description of frames).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[0-9]+[ms|s|m]&lt;/code&gt; time progression: the time progression syntax lets you progress virtual time by a specific amount. It&apos;s a number, followed by a time unit of ms (milliseconds), s (seconds), or m (minutes) without any space between them, e.g. a 10ms b.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;|&lt;/code&gt; complete: The successful completion of an observable. This is the observable producer signaling complete().&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#&lt;/code&gt; error: An error terminating the observable. This is the observable producer signaling error().&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[a-z0-9]&lt;/code&gt; e.g. &apos;a&apos; any alphanumeric character: Represents a value being emitted by the producer signaling next().&lt;/li&gt;
&lt;li&gt;&lt;code&gt;()&lt;/code&gt; sync groupings: When multiple events need to be in the same frame synchronously, parentheses are used to group those events.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;^&lt;/code&gt; subscription point: (hot observables only) shows the point at which the tested observables will be subscribed to the hot observable. This is the &quot;zero frame&quot; for that observable, every frame before the ^ will be negative. Negative time might seem pointless, but there are in fact advanced cases where this is necessary, usually involving ReplaySubjects.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;https://rxjs.dev/api/testing/TestScheduler&quot;&gt;TestScheduler&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The TestScheduler is the magician that translates the Marble Syntax to something that the Test Framework can understand. It&apos;s important to remember that we cannot use the TestScheduler to test our code all the time. For example, if the code consumes a Promise we cannot use it but we should use a traditional method.
The TestScheduler exposes us some APIs that we can use to write our tests but we start from its initialization.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { TestScheduler } from &apos;rxjs/testing&apos;;

describe(&apos;Marble Testing&apos;, () =&amp;gt; {
    let testScheduler: TestScheduler;

    beforeEach(() =&amp;gt; {
        testScheduler = new TestScheduler((actual, expected) =&amp;gt; {
            expect(actual).toEqual(expected);
        });
    });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;N.B. all the examples use &lt;a href=&quot;https://jestjs.io/&quot;&gt;jest&lt;/a&gt; as Testing Framework&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As you can see, it&apos;s important to create a new TestScheduler for every test, this allows us to have a new instance for every test and create a clean case. But the weird thing in this code is the body of the code passing to the TestScheduler. This code is particular if you are confident with any test framework because in this function we have already indicated the expectations of the test, but we haven&apos;t written one yet. This, because the TestScheduler exposes some helpers to test the code and these helpers call the function indicated in the constructor of the  TestScheduler to check the failure or the success of the test.&lt;/p&gt;
&lt;p&gt;But let&apos;s see a concrete example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { TestScheduler } from &apos;rxjs/testing&apos;;

describe(&apos;Marble Testing&apos;, () =&amp;gt; {
    let testScheduler: TestScheduler;

    beforeEach(() =&amp;gt; {
        testScheduler = new TestScheduler((actual, expected) =&amp;gt; {
            expect(actual).toEqual(expected);
        });
    });
    
    it(&apos;test&apos;, () =&amp;gt; {
        testScheduler.run((helpers) =&amp;gt; {
            const { cold, expectObservable } = helpers;
            const source$ = cold(&apos;-a-b-c|&apos;);
            const expected = &apos;-a-b-c|&apos;;
        
            expectObservable(source$).toBe(expected);
        });
    });

});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, we created a cold Observable that emits 3 values: a, b and c. Using the expectObservable helper we can test our observable by comparing it with the expectation passed to the toBe method.
Now let&apos;s add some dynamism to our tests and see how to pass values to our observable inside of the tests.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { TestScheduler } from &apos;rxjs/testing&apos;;

describe(&apos;Marble Testing&apos;, () =&amp;gt; {
    let testScheduler: TestScheduler;

    beforeEach(() =&amp;gt; {
        testScheduler = new TestScheduler((actual, expected) =&amp;gt; {
            expect(actual).toEqual(expected);
        });
    });

    it(&apos;test with values&apos;, () =&amp;gt; {
        testScheduler.run((helpers) =&amp;gt; {
            const { cold, expectObservable } = helpers;
            const source$ = cold(&apos;-a-b-c|&apos;, { a: 1, b: 2, c: 3 });
            const expected = &apos;-a-b-c|&apos;;
        
            expectObservable(source$).toBe(expected, { a: 1, b: 2, c: 3 });
        });
    });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, you can see that we can pass another argument to the cold function. This argument is an object where the fields are the correspondents of the value passed in the marble string, so if you use a, b, and c in the marble string you have to use a, b, and c as fields of your argument. The values of these fields are the values used by the test and emitted by the observable. The same goes for the toBe method, it accepts another argument where we can pass the expected result values.
Another important concept when you test your observables is the time, in these cases, it&apos;s possible to specify after how much time an observable emits a value or after how much time a value is expected. Here, an example using the &lt;code&gt;concatMap&lt;/code&gt; operator combined with the &lt;code&gt;delay&lt;/code&gt; operator that delays the result by 100ms.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { concatMap, delay, of } from &apos;rxjs&apos;;
import { TestScheduler } from &apos;rxjs/testing&apos;;

describe(&apos;Marble Testing&apos;, () =&amp;gt; {
    let testScheduler: TestScheduler;

    beforeEach(() =&amp;gt; {
        testScheduler = new TestScheduler((actual, expected) =&amp;gt; {
            expect(actual).toEqual(expected);
        });
    });
    
    it(&apos;test&apos;, () =&amp;gt; {
        testScheduler.run((helpers) =&amp;gt; {
            const { cold, expectObservable } = helpers;
            const source$ = cold(&apos;-a-b-c|&apos;);
            const final$ = source$.pipe(concatMap(val =&amp;gt; of(val).pipe(delay(100))));
            const expected = &apos;- 100ms a 99ms b 99ms (c|)&apos;;
            expectObservable(final$).toBe(expected);
        });
    });

});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the previous examples I showed you how to test cold Observables, but you can test hot observables too.
One of the important concepts, when you create a hot Observable, is that you can indicate when the observables are subscribed, and you can do that using the &lt;code&gt;^&lt;/code&gt; character.
When you indicate the subscription you might remember that your results start from the subscription and the values emitted before are ignored by the test. You can see an example below.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { TestScheduler } from &apos;rxjs/testing&apos;;

describe(&apos;Marble Testing&apos;, () =&amp;gt; {
    let testScheduler: TestScheduler;

    beforeEach(() =&amp;gt; {
        testScheduler = new TestScheduler((actual, expected) =&amp;gt; {
            expect(actual).toEqual(expected);
        });
    });
    
    it(&apos;test&apos;, () =&amp;gt; {
        testScheduler.run((helpers) =&amp;gt; {
            const { hot, expectObservable } = helpers;
            const source$ = hot(&apos;-a-b-^-c|&apos;);
            const expected = &apos;--c|&apos;;
            expectObservable(source$).toBe(expected);
        });
    });

});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last test case that I&apos;ll show you today is how to test the subscriptions. Sometimes could be necessary to test when an observable is subscribed and for how much time.
Let me use an example: we have two observables combined together using a concat operator, in this case, we need to test if the first observable is subscribed and when it is completed we need to check if the second observable is subscribed.
While you are before these cases, you need to use the &lt;code&gt;expectSubscriptions&lt;/code&gt; helper. This helper allows you to check the subscriptions of an observable and detects when the observable is subscribed and when is unsubscribed.
Here you can find the example explained above.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { concat } from &apos;rxjs&apos;;
import { TestScheduler } from &apos;rxjs/testing&apos;;

describe(&apos;Marble Testing&apos;, () =&amp;gt; {
    let testScheduler: TestScheduler;

    beforeEach(() =&amp;gt; {
        testScheduler = new TestScheduler((actual, expected) =&amp;gt; {
            expect(actual).toEqual(expected);
        });
    });
    
    it(&apos;test subscriptions&apos;, () =&amp;gt; {
        testScheduler.run((helpers) =&amp;gt; {
            const { cold, expectObservable, expectSubscriptions } = helpers;
            const source1$ = cold(&apos;-a-b-c|&apos;);
            const source2$ = cold(&apos;-d-e-f|&apos;);
            const final$ = concat(source1$, source2$);

            const expected = &apos;-a-b-c-d-e-f|&apos;;
            const expectedSubscriptionsSource1 = &apos;^-----!&apos;;
            const expectedSubscriptionsSource2 = &apos;------^-----!&apos;;

            expectObservable(final$).toBe(expected);
            expectSubscriptions(source1$.subscriptions).toBe(expectedSubscriptionsSource1);
            expectSubscriptions(source2$.subscriptions).toBe(expectedSubscriptionsSource2);
        });
    });

});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok guys, I think that&apos;s enough for today. &lt;a href=&quot;https://github.com/Puppo/rxjs-getting-started/tree/15-testing&quot;&gt;in the GitHub repository&lt;/a&gt; you can find the code of this article.
But before I let you go, I have bad news unfortunately, this is the last article of the series, so today there will be some special regards.
I hope you enjoyed this series and you understood better the RxJS world.
Thanks for having read the series and if you have any doubts don&apos;t hesitate to contact me, I will be happy to help you.&lt;/p&gt;
&lt;p&gt;I will be back soon with new contents, see you soon guys, stay subscribed, and bye-bye.&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Subjects</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-subjects/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-subjects/</guid><description>What&apos;s a Subject Luca? And why today do you want to speak about subjects? Is there a mistake in the...</description><pubDate>Wed, 06 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;What&apos;s a Subject Luca? And why today do you want to speak about subjects? Is there a mistake in the publishing? Or are you simply drunk?
&lt;/p&gt;
&lt;p&gt;No guys, don&apos;t worry, It&apos;s the topic of the day :)
I think that after this long trip in the RxJS world and after Observables, Observers, Subscriptions, and a number of Operators that I don&apos;t even remember, it&apos;s time to show you the Subjects, a powerful type of Observable, but not only.
Let&apos;s start from the definition:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
Ok, I&apos;m joking :)
But let&apos;s continue with two notes present in the official documentation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Every Subject is an Observable&lt;/strong&gt;
Given a Subject, you can subscribe to it, providing an Observer, which will start receiving values normally. From the perspective of the Observer, it cannot tell whether the Observable execution is coming from a plain unicast Observable or a Subject.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Every Subject is an Observer&lt;/strong&gt;
It is an object with the methods next(v), error(e), and complete(). To feed a new value to the Subject, just call next(theValue), and it will be multicasted to the Observers registered to listen to the Subject.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ok, but what does it means?
It means that you can create a Subject, subscribe to it with infinitive observers, multicast the values with great performance, emit new values using a simple method called &lt;code&gt;next&lt;/code&gt;, emit errors using a method called &lt;code&gt;error&lt;/code&gt; and complete your subject with a simple method called &lt;code&gt;complete&lt;/code&gt;.
The icing on that cake is that all these things can be done with a clean code and they are not enclosed into the body of a function as on the Observable constructor.&lt;/p&gt;
&lt;p&gt;But let me show you an example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Subject } from &apos;rxjs&apos;;
 
const subject = new Subject&amp;lt;number&amp;gt;();
 
subject.subscribe({
  next: (v) =&amp;gt; console.log(new Date().toLocaleTimeString(), `observerA: ${v}`),
  complete: () =&amp;gt; console.log(new Date().toLocaleTimeString(), &apos;observerA: complete&apos;)
});
 
subject.next(1);

setTimeout(() =&amp;gt; {
  subject.subscribe({
  next: (v) =&amp;gt; console.log(new Date().toLocaleTimeString(), `observerB: ${v}`),
  complete: () =&amp;gt; console.log(new Date().toLocaleTimeString(), &apos;observerB: complete&apos;)
});
}, 2000);

setTimeout(() =&amp;gt; {
  subject.next(2);
}, 3000);

setTimeout(() =&amp;gt; {
  subject.complete();
}, 4000);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;18:52:23 observerA: 1
18:52:26 observerA: 2
18:52:26 observerB: 2
18:52:27 observerA: complete
18:52:27 observerB: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;As you can see, with a Subject we can emit new values, subscribe to its changes, and complete the subject.
I recommend you to try this special observable because it can be powerful in many cases.&lt;/p&gt;
&lt;p&gt;The RxJS library does not stop its power here. It exposes us four different types of subjects: Subject, BehaviorSubject, ReplaySubject and AsyncSubject.
These four types have 4 different behaviour that can help us to resolve different cases. Let me show you these differences.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/guide/subject#subject&quot;&gt;subject&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;A Subject is like an Observable, but can multicast to many Observers. Subjects are like EventEmitters: they maintain a registry of many listeners.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Subject } from &apos;rxjs&apos;;
 
const subject = new Subject&amp;lt;number&amp;gt;();
 
subject.subscribe({
  next: (v) =&amp;gt; console.log(new Date().toLocaleTimeString(), `observerA: ${v}`),
  complete: () =&amp;gt; console.log(new Date().toLocaleTimeString(), &apos;observerA: complete&apos;)
});
 
subject.next(1);

setTimeout(() =&amp;gt; {
    subject.subscribe({
        next: (v) =&amp;gt; console.log(new Date().toLocaleTimeString(), `observerB: ${v}`),
        complete: () =&amp;gt; console.log(new Date().toLocaleTimeString(), &apos;observerB: complete&apos;)
    });
}, 1000);

setTimeout(() =&amp;gt; {
  subject.next(2);
}, 3000);

setTimeout(() =&amp;gt; {
  subject.complete();
}, 4000);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;19:14:41 observerA: 1
19:14:44 observerA: 2
19:14:44 observerB: 2
19:14:45 observerA: complete
19:14:45 observerB: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;This subject can be used when we need to emit values and notify some of these.
This subject doesn&apos;t have an initial value and if an observer subscribes to this type of subject it receives only the values emitted after its subscription.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;N.B. In some cases, we don&apos;t need to send a value when we call the next method of the subject, but we just need to call the method to notify some of these. In these cases, we can use the &lt;a href=&quot;https://rxjs.dev/guide/subject#void-subject&quot;&gt;Void Subject&lt;/a&gt;, a special subject that does not need a value.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/guide/subject#behaviorsubject&quot;&gt;behaviorsubject&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;BehaviorSubjects are useful for representing &quot;values over time&quot;. For instance, an event stream of birthdays is a Subject, but the stream of a person&apos;s age would be a BehaviorSubject.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { BehaviorSubject } from &apos;rxjs&apos;;
 
const subject = new BehaviorSubject&amp;lt;number&amp;gt;(0);
 
subject.subscribe({
  next: (v) =&amp;gt; console.log(new Date().toLocaleTimeString(), `observerA: ${v}`),
  complete: () =&amp;gt; console.log(new Date().toLocaleTimeString(), &apos;observerA: complete&apos;)
});
 
subject.next(1);

setTimeout(() =&amp;gt; {
    subject.subscribe({
        next: (v) =&amp;gt; console.log(new Date().toLocaleTimeString(), `observerB: ${v}`),
        complete: () =&amp;gt; console.log(new Date().toLocaleTimeString(), &apos;observerB: complete&apos;)
    });
}, 1000);

setTimeout(() =&amp;gt; {
  subject.next(2);
}, 3000);

setTimeout(() =&amp;gt; {
  subject.complete();
}, 4000);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;19:15:57 observerA: 0
19:15:57 observerA: 1
19:15:58 observerB: 1
19:16:00 observerA: 2
19:16:00 observerB: 2
19:16:01 observerA: complete
19:16:01 observerB: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
The BehaviorSubject is a subject that requires an initial value. When an observer subscribes to a BehaviorSubject it immediately receives the last emitted value and then it waits for the future values.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/guide/subject#replaysubject&quot;&gt;replaysubject&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;A ReplaySubject records multiple values from the Observable execution and replays them to new subscribers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { ReplaySubject } from &apos;rxjs&apos;;
 
const subject = new ReplaySubject&amp;lt;number&amp;gt;();
 
subject.subscribe({
  next: (v) =&amp;gt; console.log(new Date().toLocaleTimeString(), `observerA: ${v}`),
  complete: () =&amp;gt; console.log(new Date().toLocaleTimeString(), &apos;observerA: complete&apos;)
});
 
subject.next(1);

setTimeout(() =&amp;gt; {
  subject.next(2);
}, 1000);

setTimeout(() =&amp;gt; {
    subject.subscribe({
        next: (v) =&amp;gt; console.log(new Date().toLocaleTimeString(), `observerB: ${v}`),
        complete: () =&amp;gt; console.log(new Date().toLocaleTimeString(), &apos;observerB: complete&apos;)
    });
}, 2000);

setTimeout(() =&amp;gt; {
  subject.next(3);
}, 3000);

setTimeout(() =&amp;gt; {
  subject.complete();
}, 4000);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;19:17:37 observerA: 1
19:17:38 observerA: 2
19:17:39 observerB: 1
19:17:39 observerB: 2
19:17:40 observerA: 3
19:17:40 observerB: 3
19:17:41 observerA: complete
19:17:41 observerB: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
The ReplaySubject is a subject that doesn&apos;t require an initial value but when an observer subscribes to it, it receives immediately all the values already emitted and after that, it waits for the future values.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/guide/subject#asyncsubject&quot;&gt;asyncsubject&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;The AsyncSubject is a variant where only the last value of the Observable execution is sent to its observers, and only when the execution completes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { AsyncSubject } from &apos;rxjs&apos;;
 
const subject = new AsyncSubject&amp;lt;number&amp;gt;();
 
subject.subscribe({
  next: (v) =&amp;gt; console.log(new Date().toLocaleTimeString(), `observerA: ${v}`),
  complete: () =&amp;gt; console.log(new Date().toLocaleTimeString(), &apos;observerA: complete&apos;)
});
 
subject.next(1);

setTimeout(() =&amp;gt; {
    subject.subscribe({
        next: (v) =&amp;gt; console.log(new Date().toLocaleTimeString(), `observerB: ${v}`),
        complete: () =&amp;gt; console.log(new Date().toLocaleTimeString(), &apos;observerB: complete&apos;)
    });
}, 1000);

setTimeout(() =&amp;gt; {
  subject.next(2);
}, 3000);

setTimeout(() =&amp;gt; {
  subject.complete();
}, 4000);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;19:19:01 observerA: 2
19:19:01 observerB: 2
19:19:01 observerA: complete
19:19:01 observerB: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
The AsyncSubject is a subject that does not emit values ​​until it is completed, at the time of its completion it emits the last value executed.&lt;/p&gt;
&lt;p&gt;These are the differences between these subjects, it&apos;s important to remember these differences because if you choose the wrong subject you could do unexpected mistakes.&lt;/p&gt;
&lt;p&gt;Before ending the article let me show you a best practice to expose our subject to the consumers. If you need to hide to your consumers that your Observable is a Subject, you need to expose the subject using its &quot;asObservable&quot; method. This method returns the subject as an Observable, so the consumer can&apos;t call the &quot;next&quot; and &quot;complete&quot; methods.&lt;/p&gt;
&lt;p&gt;Ok guys, that&apos;s all for today, I recommend you to play with these subject to understand better their power and characteristics.&lt;/p&gt;
&lt;p&gt;See you soon
Bye Bye&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Custom Operators</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-custom-operators/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-custom-operators/</guid><description>Hi Folks 👋 after many articles in which I have illustrated the different types of operators already...</description><pubDate>Mon, 04 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Folks 👋
after many articles in which I have illustrated the different types of operators already included in the RxJS library, today I show you how to create your own operators.
You can create a new operator in two ways: mixing the different operators illustrated in the previous articles or from scratch.
In common cases, when we need to create a new operator, all the behaviours that we need already exist in the operators exposed by the RxJS library. In these cases, we can use the &quot;pipe&quot; function to combine together the operators. With the &quot;pipe&quot; function you can create a new function that will be the new operator, and inside this function you can create the logic of your operator.
Here&apos;s an example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { delay, interval, Observable, pipe, take, tap, UnaryFunction } from &apos;rxjs&apos;;

function takeLogAndDelay&amp;lt;T&amp;gt;(takeNumber: number, message: string, time: number): UnaryFunction&amp;lt;Observable&amp;lt;T&amp;gt;, Observable&amp;lt;T&amp;gt;&amp;gt; {
  return pipe(
    tap(x =&amp;gt; console.log(message, x)),
    take(takeNumber),
    delay(time),
  );
}

interval(1000).pipe(
    takeLogAndDelay(10, &apos;Source&apos;, 2000)
).subscribe();
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Source 0
Source 1
Source 2
Source 3
Source 4
Source 5
Source 6
Source 7
Source 8
Source 9
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, in the last example I created a new operator called &quot;takeLogAndDelay&quot;. This operator combines together three operators: tap, take and delay.
As you can see, it&apos;s easy to create a new operator of this type and you just need to flow these rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;create a new function with the name of the new operator&lt;/li&gt;
&lt;li&gt;return the pipe function&lt;/li&gt;
&lt;li&gt;combine the operators in the pipe function&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In 95% of your cases, you can resolve your problem and create a new operator using this method, while in the 5% of the cases not managed by this method you can create a new operator from scratch.
Below an example of the delay operator created from scratch.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Observable, of } from &apos;rxjs&apos;;
import { tap } from &apos;rxjs/operators&apos;;

function delay&amp;lt;T&amp;gt;(delayInMs: number) {
  return (observable: Observable&amp;lt;T&amp;gt;) =&amp;gt;
    new Observable&amp;lt;T&amp;gt;((subscriber) =&amp;gt; {
      const allTimerIDs = new Set&amp;lt;NodeJS.Timeout&amp;gt;();
      let hasCompleted = false;
      const subscription = observable.subscribe({
        next(value) {
          const timerID = setTimeout(() =&amp;gt; {
            subscriber.next(value);
            allTimerIDs.delete(timerID);
            if (hasCompleted &amp;amp;&amp;amp; allTimerIDs.size === 0) {
              subscriber.complete();
            }
          }, delayInMs);

          allTimerIDs.add(timerID);
        },
        error: subscriber.error,
        complete() {
          hasCompleted = true;
          if (allTimerIDs.size === 0) {
            subscriber.complete();
          }
        },
      });

      return () =&amp;gt; {
        subscription.unsubscribe();
        allTimerIDs.forEach((timerID) =&amp;gt; clearTimeout(timerID));
      };
    });
}

of(1, 2, 3).pipe(
    tap((value) =&amp;gt; console.log(new Date().toLocaleTimeString(), &quot;before&quot;, value)),
    delay(3000)
).subscribe({
    next: (value) =&amp;gt; console.log(new Date().toLocaleTimeString(), &quot;after&quot;, value),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;22:11:01 before 1
22:11:01 before 2
22:11:01 before 3
22:11:04 after 1
22:11:04 after 2
22:11:04 after 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, we can create a new operator and manage all the behaviours needed for our logic using the Observable constructor. It&apos;s rare to use this approach but if you find yourself in front of a case not yet solved by the existing operators, you can rely on it.&lt;/p&gt;
&lt;p&gt;Ok guys, that&apos;s all for today.&lt;/p&gt;
&lt;p&gt;See you soon
Bye bye 👋&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Multicast Operator</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-multicast-operator/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-multicast-operator/</guid><description>Hi Folk 👋, in the previous articles we&apos;ve seen that when we subscribe to an observable, the...</description><pubDate>Fri, 01 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Folk 👋,
in the previous articles we&apos;ve seen that when we subscribe to an observable, the observable restarts every time and do not remember the last value emitted.
In some cases, this behaviour can not be the right solution, so today I&apos;ll show you how to share the values using the Multicast Operators.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/share&quot;&gt;share&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns a new Observable that multicasts (shares) the original Observable. As long as there is at least one Subscriber this Observable will be subscribed and emitting data. When all subscribers have unsubscribed it will unsubscribe from the source Observable. Because the Observable is multicasting it makes the stream hot.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;/**
marble share
{
    source a:           +--0-1-2-3-4-#
    operator share:     {
        +--0-1-2-3-4-#
        ......+2-3-4-#
    }
}
*/
import { interval } from &apos;rxjs&apos;;
import { share, take, tap } from &apos;rxjs/operators&apos;;
 
const source1 = interval(1000)
.pipe(
    take(5),
    tap((x: number) =&amp;gt; console.log(&apos;Processing: &apos;, x)),
    share()
);

source1.subscribe({
    next: x =&amp;gt; console.log(&apos;subscription 1: &apos;, x),
    complete: () =&amp;gt; console.log(&apos;subscription 1 complete&apos;),
});

setTimeout(() =&amp;gt; {
    source1.subscribe({
        next: x =&amp;gt; console.log(&apos;subscription 2: &apos;, x),
        complete: () =&amp;gt; console.log(&apos;subscription 2 complete&apos;),
    });
}, 3000);


setTimeout(() =&amp;gt; {
    source1.subscribe({
        next: x =&amp;gt; console.log(&apos;subscription 3: &apos;, x),
        complete: () =&amp;gt; console.log(&apos;subscription 3 complete&apos;),
    });
}, 7000);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Processing:  0
subscription 1:  0
Processing:  1
subscription 1:  1
Processing:  2
subscription 1:  2
subscription 2:  2
Processing:  3
subscription 1:  3
subscription 2:  3
Processing:  4
subscription 1:  4
subscription 2:  4
subscription 1 complete
subscription 2 complete
Processing:  0
subscription 3:  0
Processing:  1
subscription 3:  1
Processing:  2
subscription 3:  2
Processing:  3
subscription 3:  3
Processing:  4
subscription 3:  4
subscription 3 complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator can help us when we need to share the value of an observable during its execution. But what does it mean? It means that the first subscription starts the observable and all the next subscriptions that subscribe to this observable do not run a new instance of the observable but they receive the same values of the first subscription, thus losing all the previous values emitted before their subscription.
It&apos;s important to remember that when the observable is completed, and another observer subscribes itself to the observable, the shared operator resets the observable and restarts its execution from the beginning.
Anyway, sometimes our code needs to prevent the restarting of our observables, but what can we do in these cases?
It&apos;s simple! The share operator exposes us some options: resetOnComplete, resetOnError, resetOnRefCountZero, and each of these options can help us to prevent the resetting of the observables in different cases. These options can work or with a simple boolean value that enables or disables the behaviour, or we can pass a notifier factory that returns an observable which grants more fine-grained control over how and when the reset should happen.
The resetOnComplete option prevents the resetting after the observable&apos;s completion. So, if it is enabled when another observer subscribes to an observable already completed this observer receives immediately the complete notification.
The resetOnError option prevents the resetting of the observable after an error notification.
The resetOnRefCountZero option works with the number of observers subscribed instead. It prevents the resetting if there aren&apos;t any observer subscribed. To better understand, if all the subscriptions of our observable are unsubscribed, and this option is enabled, the observable isn&apos;t reset. otherwise, if this option is disabled, the observable restarts from the beginning at the next subscription.
Here&apos;s an example using the resetOnRefCountZero option.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { interval, timer } from &apos;rxjs&apos;;
import { share, take } from &apos;rxjs/operators&apos;;
 
const source = interval(1000).pipe(take(3), share({ resetOnRefCountZero: () =&amp;gt; timer(1000) }));
 
const subscriptionOne = source.subscribe(x =&amp;gt; console.log(&apos;subscription 1: &apos;, x));
setTimeout(() =&amp;gt; subscriptionOne.unsubscribe(), 1300);

setTimeout(() =&amp;gt; source.subscribe(x =&amp;gt; console.log(&apos;subscription 2: &apos;, x)), 1700);

setTimeout(() =&amp;gt; source.subscribe(x =&amp;gt; console.log(&apos;subscription 3: &apos;, x)), 5000);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;subscription 1:  0
subscription 2:  1
subscription 2:  2
subscription 3:  0
subscription 3:  1
subscription 3:  2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/shareReplay&quot;&gt;shareReplay&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Share source and replay specified number of emissions on subscription.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval } from &apos;rxjs&apos;;
import { shareReplay, take, tap } from &apos;rxjs/operators&apos;;

const obs$ = interval(1000);
const shared$ = obs$.pipe(
  take(4),
  tap(console.log),
  shareReplay(3)
);
shared$.subscribe(x =&amp;gt; console.log(&apos;sub A: &apos;, x));

setTimeout(() =&amp;gt; {
  shared$.subscribe(y =&amp;gt; console.log(&apos;sub B: &apos;, y));
}, 3500);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0
sub A:  0
1
sub A:  1
2
sub A:  2
sub B:  0
sub B:  1
sub B:  2
3
sub A:  3
sub B:  3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
In some cases, when we share the values between multiple observers, if an observer subscribes to an already started observable, we also need to replay all the previous already emitted values. To resolve this problem we can use the shareReplay operator.
This operator shares the emitted values and if another observer subscribes to the observable it replays the previous values.
The number of values replayed can be configured: by default all the values already emitted are emitted again, but we can also indicate or a maximum number of elements to remember or a maximum time length.&lt;/p&gt;
&lt;p&gt;Ok guys, that&apos;s all for today.
If you are interested in trying the code of this article, you can find it &lt;a href=&quot;https://github.com/puppo/rxjs-getting-started/tree/12-multicasting-operators&quot;&gt;in the GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the next article, I&apos;ll show you how to create your custom operators.&lt;/p&gt;
&lt;p&gt;See you soon!&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Error Handling Operators</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-error-handling-operators/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-error-handling-operators/</guid><description>One of the best practice in our work is handle the errors, so today I&apos;ll show you some operators in...</description><pubDate>Wed, 29 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of the best practice in our work is handle the errors, so today I&apos;ll show you some operators in RxJS to handle the errors.
Let&apos;s start :)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/catchError&quot;&gt;catchError&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Catches errors on the observable to be handled by returning a new observable or throwing an error.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { of } from &apos;rxjs&apos;;
import { catchError, map } from &apos;rxjs/operators&apos;;
 
of(&apos;a&apos;, &apos;b&apos;, &apos;c&apos;, &apos;d&apos;, 1, 3).pipe(
    map((n: any) =&amp;gt; n.toUpperCase()),
    catchError(err =&amp;gt; {
        console.error(err.message);
        return of(&apos;A&apos;, &apos;B&apos;, &apos;C&apos;, &apos;D&apos;)
    }),
  )
  .subscribe(x =&amp;gt; console.log(x));
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;A
B
C
D
n.toUpperCase is not a function
A
B
C
D
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator is used to catch the errors during the execution of the observables.
This operator helps us to handle the errors and prevent a bad flow of our users.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/retry&quot;&gt;retry&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;import { of } from &apos;rxjs&apos;;
import { map, retry } from &apos;rxjs/operators&apos;;

function toString(val: { toString: () =&amp;gt; string }): string | never {
    console.log(&apos;toString of&apos;, val);
    if (Math.random() &amp;gt; 0.6)
        return val.toString()

    console.log(&apos;toString of&apos;, val, &apos;failed&apos;);
    throw new Error(&apos;toString failed&apos;)
}
 
of(1, 2, 3, 4, 5, 6, 7, 8, 9, 0).pipe(
    map(toString),
    retry(3)
  )
  .subscribe({
      next: x =&amp;gt; console.log(x),
      error: error =&amp;gt; console.error(error.message),
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;toString of 1
toString of 1 failed
toString of 1
toString of 1 failed
toString of 1
1
toString of 2
toString of 2 failed
toString of 1
toString of 1 failed
toString failed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator is used to retry the execution of an observable if it raises an error. We can indicate the max number of retries. If during the execution an observable raises a number of errors greater than the indicated value, the retry operator doesn&apos;t try anymore but goes out and raise the error.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/retryWhen&quot;&gt;retryWhen&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns an Observable that mirrors the source Observable with the exception of an error. If the source Observable calls error, this method will emit the Throwable that caused the error to the Observable returned from notifier. If that Observable calls complete or error then this method will call complete or error on the child subscription. Otherwise this method will resubscribe to the source Observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval, timer } from &apos;rxjs&apos;;
import { delayWhen, filter, map, retryWhen, tap } from &apos;rxjs/operators&apos;;
 
interval(1000).pipe(
  map(val =&amp;gt; {
    if (val &amp;gt; 5) {
      throw val;
    }
    return val;
  }),
  retryWhen(errors =&amp;gt;
    errors.pipe(
      tap(val =&amp;gt; console.log(`Value ${val} was too high!`)),
      filter((_, index) =&amp;gt; index &amp;lt; 3),
      delayWhen(val =&amp;gt; timer(val * 1000))
    )
  )
).subscribe({
    next: x =&amp;gt; console.log(x),
    error: error =&amp;gt; console.error(error.message),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0
1
2
3
4
5
Value 6 was too high!
0
1
2
3
4
5
Value 6 was too high!
0
1
2
3
4
5
Value 6 was too high!
0
1
2
3
4
5
Value 6 was too high!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator is used to retry the execution of an observable and it allows us to indicate the strategy of the retry.&lt;/p&gt;
&lt;p&gt;I hope you have all the means now to better handle errors in your code.
It&apos;s all for today.
You can find all the code of this article in the repository&lt;/p&gt;
&lt;p&gt;See you soon,
Bye Bye!&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Conditional &amp; Mathematical Operators</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-conditional-mathematical-operators/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-conditional-mathematical-operators/</guid><description>Hi Guys and welcome back, today I&apos;ll illustrate you two simple types of the pipeable operators:...</description><pubDate>Mon, 27 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Guys and welcome back,
today I&apos;ll illustrate you two simple types of the pipeable operators: Conditional Operators and Mathematical Operators.
No time to waste, let&apos;s start.&lt;/p&gt;
&lt;h2&gt;Conditional Operators&lt;/h2&gt;
&lt;p&gt;These operators are useful to check if there are values in the observables or to find some specific value in them. Some of these operators are similar to some array methods, with the difference that they work with observables and not with arrays.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/defaultIfEmpty&quot;&gt;defaultIfEmpty&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Emits a given value if the source Observable completes without emitting any next value, otherwise mirrors the source Observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { EMPTY, Observer } from &quot;rxjs&quot;;
import { defaultIfEmpty } from &quot;rxjs/operators&quot;;

const observer: Observer&amp;lt;number&amp;gt; = {
    next: x =&amp;gt; console.log(&apos;value&apos;, x),
    error: err =&amp;gt; console.error(&apos;error&apos;, err),
    complete: () =&amp;gt; console.log(&apos;complete&apos;),
};

EMPTY.pipe(
    defaultIfEmpty(10)
).subscribe(observer);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;value 10
complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator, as you can see, permits us to receive a default value if the observable does not emit any value.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/every&quot;&gt;every&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns an Observable that emits whether or not every item of the source satisfies the condition specified.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observer, of } from &quot;rxjs&quot;;
import { every } from &quot;rxjs/operators&quot;;

const observer: Observer&amp;lt;boolean&amp;gt; = {
    next: x =&amp;gt; console.log(&apos;value&apos;, x),
    error: err =&amp;gt; console.error(&apos;error&apos;, err),
    complete: () =&amp;gt; console.log(&apos;complete&apos;),
};

of(1,2,3,4,5,6,7,8,9).pipe(
    every(val =&amp;gt; val &amp;lt; 10)
).subscribe(observer);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;value true
complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is like the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every?retiredLocale=it&quot;&gt;every method&lt;/a&gt; in the arrays.
We can use it when we need to check if all the values of our observable meet a condition.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/find&quot;&gt;find&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Emits only the first value emitted by the source Observable that meets some condition.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observer, of } from &quot;rxjs&quot;;
import { find } from &quot;rxjs/operators&quot;;

const observer: Observer&amp;lt;number | undefined&amp;gt; = {
    next: x =&amp;gt; console.log(&apos;value&apos;, x),
    error: err =&amp;gt; console.error(&apos;error&apos;, err),
    complete: () =&amp;gt; console.log(&apos;complete&apos;),
};

of(1,2,3,4,5,6,7,8,9).pipe(
    find(val =&amp;gt; val === 5)
).subscribe(observer);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;value 5
complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is like the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find&quot;&gt;find method&lt;/a&gt; in the arrays.
We can use it to find a value that meets a condition in our observable. It&apos;s important to remember that when the operator finds a value that matches our condition it completes the observable.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/findIndex&quot;&gt;findIndex&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Emits only the index of the first value emitted by the source Observable that meets some condition.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observer, of } from &quot;rxjs&quot;;
import { findIndex } from &quot;rxjs/operators&quot;;

const observer: Observer&amp;lt;number&amp;gt; = {
    next: x =&amp;gt; console.log(&apos;value&apos;, x),
    error: err =&amp;gt; console.error(&apos;error&apos;, err),
    complete: () =&amp;gt; console.log(&apos;complete&apos;),
};

of(1,2,3,4,5,6,7,8,9).pipe(
    findIndex(val =&amp;gt; val === 5)
).subscribe(observer);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;value 4
complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is like the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex&quot;&gt;findIndex method&lt;/a&gt; in the arrays.
We can use it to find the index of a value that meets a condition in our observable. It&apos;s important to remember that when the operator finds a value that matches our condition it completes the observable.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/isEmpty&quot;&gt;isEmpty&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Emits false if the input Observable emits any values, or emits true if the input Observable completes without emitting any values.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { EMPTY, Observer } from &quot;rxjs&quot;;
import { isEmpty } from &quot;rxjs/operators&quot;;

const observer: Observer&amp;lt;boolean&amp;gt; = {
    next: x =&amp;gt; console.log(&apos;value&apos;, x),
    error: err =&amp;gt; console.error(&apos;error&apos;, err),
    complete: () =&amp;gt; console.log(&apos;complete&apos;),
};

EMPTY.pipe(
    isEmpty()
).subscribe(observer);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;value true
complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is used to check if an observable has emitted at least a value.&lt;/p&gt;
&lt;h2&gt;Mathematical Operators&lt;/h2&gt;
&lt;p&gt;These operators are used to retrieve some special values in our observables or to reduce the values.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/count&quot;&gt;count&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Counts the number of emissions on the source and emits that number when the source is completed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observer, of } from &quot;rxjs&quot;;
import { count } from &quot;rxjs/operators&quot;;

const observer: Observer&amp;lt;number | undefined&amp;gt; = {
    next: x =&amp;gt; console.log(&apos;value&apos;, x),
    error: err =&amp;gt; console.error(&apos;error&apos;, err),
    complete: () =&amp;gt; console.log(&apos;complete&apos;),
};

of(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;).pipe(
    count()
).subscribe(observer);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;value 5
complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is used to count the values of our observables.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/max&quot;&gt;max&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;The Max operator operates on an Observable that emits numbers (or items that can be compared with a provided function), and when source Observable completes it emits a single item: the item with the largest value.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observer, of } from &quot;rxjs&quot;;
import { max } from &quot;rxjs/operators&quot;;

const observer: Observer&amp;lt;string&amp;gt; = {
    next: x =&amp;gt; console.log(&apos;value&apos;, x),
    error: err =&amp;gt; console.error(&apos;error&apos;, err),
    complete: () =&amp;gt; console.log(&apos;complete&apos;),
};

of(&quot;a&quot;, &quot;b&quot;, &quot;e&quot;, &quot;d&quot;, &quot;c&quot;).pipe(
    max()
).subscribe(observer);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;value e
complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is used to get the maximum value emitted by our  observables.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/min&quot;&gt;min&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;The Min operator operates on an Observable that emits numbers (or items that can be compared with a provided function), and when source Observable completes it emits a single item: the item with the smallest value.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observer, of } from &quot;rxjs&quot;;
import { min } from &quot;rxjs/operators&quot;;

const observer: Observer&amp;lt;string&amp;gt; = {
    next: x =&amp;gt; console.log(&apos;value&apos;, x),
    error: err =&amp;gt; console.error(&apos;error&apos;, err),
    complete: () =&amp;gt; console.log(&apos;complete&apos;),
};

of(&quot;a&quot;, &quot;b&quot;, &quot;e&quot;, &quot;d&quot;, &quot;c&quot;).pipe(
    min()
).subscribe(observer);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;value a
complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is used to get the minimum value emitted by our  observables.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/reduce&quot;&gt;reduce&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Applies an accumulator function over the source Observable, and returns the accumulated result when the source completes, given an optional seed value.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observer, of } from &quot;rxjs&quot;;
import { reduce } from &quot;rxjs/operators&quot;;

const observer: Observer&amp;lt;number&amp;gt; = {
    next: x =&amp;gt; console.log(&apos;value&apos;, x),
    error: err =&amp;gt; console.error(&apos;error&apos;, err),
    complete: () =&amp;gt; console.log(&apos;complete&apos;),
};

of(1,2,3,4,5,6,7,8,9).pipe(
    reduce((acc, curr) =&amp;gt; acc + curr, 0)
).subscribe(observer);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;value 45
complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is like the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce&quot;&gt;reduce method&lt;/a&gt; of the array.
It can be used to reduce all the emitted values. The reduced algorithm has to be implemented by us.&lt;/p&gt;
&lt;p&gt;Ok, That&apos;s all for today.
I hope these simple operators can help you in the future as they did me.&lt;/p&gt;
&lt;p&gt;See you in the next article!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can find the code of this article &lt;a href=&quot;https://github.com/Puppo/rxjs-getting-started/tree/11-condition-and-mathematical-operators&quot;&gt;in the GitHub repository&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Utility Operators</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-utility-operators/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-utility-operators/</guid><description>Welcome back Guys, Today I&apos;ll show you some utility operators. Let&apos;s start :) tap Used to...</description><pubDate>Fri, 24 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome back Guys,
Today I&apos;ll show you some utility operators.
Let&apos;s start :)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/tap&quot;&gt;tap&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Used to perform side-effects for notifications from the source observable&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { of } from &apos;rxjs&apos;
import { tap } from &apos;rxjs/operators&apos;


of(&apos;a&apos;, &apos;b&apos;, &apos;c&apos;)
  .pipe(
      tap({
          next: x =&amp;gt; console.log(`tap: ${x}`),
          complete: () =&amp;gt; console.log(&apos;tap: complete&apos;),
          error: err =&amp;gt; console.log(`tap: error: ${err}`)
      })
  )
  .subscribe()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;tap: a
tap: b
tap: c
tap: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator helps us to get some info about the observable during its execution. This operator is equal to the subscriber and it uses three methods to get info: next, complete, and error.
What could happen in these three methods? Exactly what you want :) You can run a side-effect or log the values. Usually I prefer logging info in this operator and not run side effects because at times side effects are difficult to test.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/delay&quot;&gt;delay&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Delays the emission of items from the source Observable by a given timeout or until a given Date.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { of } from &apos;rxjs&apos;
import { delay, tap } from &apos;rxjs/operators&apos;


of(&apos;a&apos;, &apos;b&apos;, &apos;c&apos;)
  .pipe(
      tap(x =&amp;gt; console.log(`${new Date().toLocaleTimeString()} tap before delay: ${x}`)),
      delay(1000),
      tap(x =&amp;gt; console.log(`${new Date().toLocaleTimeString()} tap after delay: ${x}`)),
  )
  .subscribe()
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;17:08:26 tap before delay: a
17:08:26 tap before delay: b
17:08:26 tap before delay: c
17:08:27 tap after delay: a
17:08:27 tap after delay: b
17:08:27 tap after delay: c
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is used to wait some specific time before emitting the value.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/timestamp&quot;&gt;timestamp&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Attaches a timestamp to each item emitted by an observable indicating when it was emitted&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { of } from &apos;rxjs&apos;
import { timestamp } from &apos;rxjs/operators&apos;

of(&apos;a&apos;, &apos;b&apos;, &apos;c&apos;)
  .pipe(
      timestamp()
  )
  .subscribe(console.log)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;{ value: &apos;a&apos;, timestamp: 1629385746523 }
{ value: &apos;b&apos;, timestamp: 1629385746528 }
{ value: &apos;c&apos;, timestamp: 1629385746528 }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator is used to attach a timestamp to each emitted item. The timestamp indicates the time when the value was emitted.
This operator can be helpful during debugging or if we need to have info about the time emission of the value.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/timeout&quot;&gt;timeout&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Errors if Observable does not emit a value in given time span.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable, throwError } from &apos;rxjs&apos;;
import { timeout } from &apos;rxjs/operators&apos;;

const source$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
    let id: NodeJS.Timeout | undefined
    (function next(count = 0) {
        if (count &amp;gt; 10) {
            subscriber.complete();
            return;
        }
        id = setTimeout(() =&amp;gt; {
            subscriber.next(count)
            next(count + 1)
        }, Math.random() &amp;gt; 0.9 ? 2000 : 1000);
    })()

    return () =&amp;gt; {
        if (id) {
            clearTimeout(id);
        }
    }

})

source$
  .pipe(
      timeout({ each: 1500, with: info =&amp;gt; throwError(() =&amp;gt; new Error(`Timeout ${1500}ms: info: ${JSON.stringify(info)}`)) }),
  )
  .subscribe({
      next: console.log,
      error: error =&amp;gt; {
          console.error(`Something Wrong!`)
          console.error(error.message)
      }
  })
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;0
1
2
3
4
5
6
7
8
Something Wrong!
Timeout 1500ms: info: {&quot;meta&quot;:null,&quot;lastValue&quot;:null,&quot;seen&quot;:9}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator checks the time of the execution of the observable, if the value is not emitted within the timeout time the operator throws an error.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/toArray&quot;&gt;toArray&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Collects all source emissions and emits them as an array when the source completes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { of } from &apos;rxjs&apos;
import { toArray } from &apos;rxjs/operators&apos;


of(&apos;a&apos;, &apos;b&apos;, &apos;c&apos;, &apos;d&apos;, &apos;e&apos;, &apos;f&apos;, &apos;g&apos;, &apos;h&apos;)
  .pipe(
      toArray()
  )
  .subscribe(console.log)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[
  &apos;a&apos;, &apos;b&apos;, &apos;c&apos;,
  &apos;d&apos;, &apos;e&apos;, &apos;f&apos;,
  &apos;g&apos;, &apos;h&apos;
]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator converts a sequence of values in one array, where all the array&apos;s items are the emitted values in sequence.&lt;/p&gt;
&lt;p&gt;Ok Guys, from the Utilities Operators is all.
&lt;a href=&quot;https://github.com/Puppo/rxjs-getting-started/tree/09-utility-operators&quot;&gt;in the GitHub repository&lt;/a&gt; you can find all the code of this article.&lt;/p&gt;
&lt;p&gt;See you soon,
Bye Bye!&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Join Operators</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-join-operators/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-join-operators/</guid><description>Hi Guys and Welcome Back, Today I&apos;ll speak about the Join Operators. Some of these operators are...</description><pubDate>Wed, 22 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Guys and Welcome Back,
Today I&apos;ll speak about the Join Operators. Some of these operators are similar to other operators shown in the &lt;a href=&quot;https://dev.to/this-is-learning/rxjs-creation-operators-6bh&quot;&gt;Creation Operators&lt;/a&gt; but they are used in different contexts, ok let&apos;s start!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/combineLatestAll&quot;&gt;combineLatestAll&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Flattens an Observable-of-Observables by applying combineLatest when the Observable-of-Observables completes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval, timer } from &apos;rxjs&apos;;
import { combineLatestAll, map, take } from &apos;rxjs/operators&apos;;

const A_CHAR_CODE = 65
const createSource = (index: number) =&amp;gt;
    interval((index + 1) * 1000).pipe(
        take(3),
        map(value =&amp;gt; `${String.fromCharCode(A_CHAR_CODE + index)}${String.fromCharCode(A_CHAR_CODE + value)}`)
    )

console.log(`${new Date().toLocaleTimeString()}: combineLatestAll start`)
const source$ = timer(0, 1000).pipe(
    take(3)
);
source$.pipe(
    map(createSource),
    combineLatestAll()
).subscribe({
    next: val =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: combineLatestAll`, val)
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;16:22:07: combineLatestAll start
16:22:12: combineLatestAll [ &apos;AB&apos;, &apos;BA&apos;, &apos;CA&apos; ]
16:22:12: combineLatestAll [ &apos;AC&apos;, &apos;BA&apos;, &apos;CA&apos; ]
16:22:13: combineLatestAll [ &apos;AC&apos;, &apos;BB&apos;, &apos;CA&apos; ]
16:22:15: combineLatestAll [ &apos;AC&apos;, &apos;BB&apos;, &apos;CB&apos; ]
16:22:15: combineLatestAll [ &apos;AC&apos;, &apos;BC&apos;, &apos;CB&apos; ]
16:22:18: combineLatestAll [ &apos;AC&apos;, &apos;BC&apos;, &apos;CC&apos; ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
As you can see, this operator is the brother of the combineLatest operator discussed in a previous article &lt;a href=&quot;https://dev.to/this-is-learning/rxjs-creation-operators-6bh&quot;&gt;RxJS - Creation Operators&lt;/a&gt;.
Its job is to convert an Observable of Observables to an array of values, where each item of this array is a value of an observable.
When we use this operator we need to remember that the first value emitted by the operator is when all the observables have emitted at least one value.
This operator is used when in the pipe chain we have an operator that emits a list of observables; using this operator we can flat the values in a single array including all the values emitted by these observables.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/concatAll&quot;&gt;concatAll&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Converts a higher-order Observable into a first-order Observable by concatenating the inner Observables in order.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval, timer } from &apos;rxjs&apos;;
import { concatAll, map, take } from &apos;rxjs/operators&apos;;

const createSource = (index: number) =&amp;gt; interval(index * 1000).pipe(
        take(3),
        map(value =&amp;gt; `${index}-${value + 1}`)
    )

console.log(`${new Date().toLocaleTimeString()}: concatAll start`)
const source$ = timer(0, 1000).pipe(
    take(3)
);
source$.pipe(
    map(v =&amp;gt; createSource(v + 1)),
    concatAll()
).subscribe({
    next: val =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: concatAll`, val)
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;15:38:29: concatAll start
15:38:30: concatAll 1-1
15:38:31: concatAll 1-2
15:38:32: concatAll 1-3
15:38:34: concatAll 2-1
15:38:36: concatAll 2-2
15:38:38: concatAll 2-3
15:38:41: concatAll 3-1
15:38:44: concatAll 3-2
15:38:47: concatAll 3-3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
The concatAll operator concatenates an Observable of Observables and emits all the observables in sequence.
It&apos;s important to remember that when we use this operator, the observables are running one after the other, so the operator executes the first observable until it isn&apos;t completed, then it passes to the second observable, and so on.
This operator is used when we have in a pipe chain an operator that returns a list of observables and we need to execute them in sequence.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/exhaustAll&quot;&gt;exhaustAll&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Converts a higher-order Observable into a first-order Observable by dropping inner Observables while the previous inner Observable has not yet completed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval, timer } from &apos;rxjs&apos;;
import { exhaustAll, map, take } from &apos;rxjs/operators&apos;;

const createSource = (index: number) =&amp;gt; interval(index * 1000).pipe(
        take(3),
        map(value =&amp;gt; `${index}-${value + 1}`)
    )

console.log(`${new Date().toLocaleTimeString()}: exhaustAll start`)
const source$ = timer(0, 2500).pipe(
    take(3)
);
source$.pipe(
    map(v =&amp;gt; createSource(v + 1)),
    exhaustAll()
).subscribe({
    next: val =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: exhaustAll`, val)
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;16:27:05: exhaustAll start
16:27:07: exhaustAll 1-1
16:27:08: exhaustAll 1-2
16:27:09: exhaustAll 1-3
16:27:14: exhaustAll 3-1
16:27:17: exhaustAll 3-2
16:27:20: exhaustAll 3-3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/mergeAll&quot;&gt;mergeAll&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Converts a higher-order Observable into a first-order Observable which concurrently delivers all values that are emitted on the inner Observables.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval, timer } from &apos;rxjs&apos;;
import { map, mergeAll, take } from &apos;rxjs/operators&apos;;

const createSource = (index: number) =&amp;gt; interval(index * 1000).pipe(
        take(3),
        map(value =&amp;gt; `${index}-${value + 1}`),
    )

console.log(`${new Date().toLocaleTimeString()}: mergeAll start`)
const source$ = timer(0, 1000).pipe(
    take(3),
);
source$.pipe(
    map(v =&amp;gt; createSource(v + 1)),
    mergeAll()
).subscribe({
    next: val =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: mergeAll`, val)
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;15:41:46: mergeAll start
15:41:47: mergeAll 1-1
15:41:48: mergeAll 1-2
15:41:49: mergeAll 2-1
15:41:49: mergeAll 1-3
15:41:51: mergeAll 3-1
15:41:51: mergeAll 2-2
15:41:53: mergeAll 2-3
15:41:54: mergeAll 3-2
15:41:57: mergeAll 3-3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/switchAll&quot;&gt;switchAll&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Converts a higher-order Observable into a first-order Observable producing values only from the most recent observable sequence&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval, timer } from &apos;rxjs&apos;;
import { map, switchAll, take } from &apos;rxjs/operators&apos;;

const createSource = (index: number) =&amp;gt; interval(index * 1000).pipe(
        take(3),
        map(value =&amp;gt; `${index}-${value + 1}`)
    )

console.log(`${new Date().toLocaleTimeString()}: switchAll start`)
const source$ = timer(0, 1000).pipe(
    take(3)
);
source$.pipe(
    map(v =&amp;gt; createSource(v + 1)),
    switchAll()
).subscribe({
    next: val =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: switchAll`, val)
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;15:42:48: switchAll start
15:42:49: switchAll 1-1
15:42:53: switchAll 3-1
15:42:56: switchAll 3-2
15:42:59: switchAll 3-3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/startWith&quot;&gt;startWith&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns an observable that, at the moment of subscription, will synchronously emit all values provided to this operator, then subscribe to the source and mirror all of its emissions to subscribers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { of } from &apos;rxjs&apos;;
import { startWith } from &apos;rxjs/operators&apos;;

const source1$ = of(1, 2, 3).pipe(
    startWith(1000)
)

source1$.subscribe({
    next: val =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: startWith`, val)
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;15:43:47: startWith 1000
15:43:47: startWith 1
15:43:47: startWith 2
15:43:47: startWith 3
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/withLatestFrom&quot;&gt;withLatestFrom&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Combines the source Observable with other Observables to create an Observable whose values are calculated from the latest values of each, only when the source emits.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;
import { interval } from &apos;rxjs&apos;;
import { take, withLatestFrom } from &apos;rxjs/operators&apos;;

const source1$ = interval(1000).pipe(
    take(5)
)
const source2$ = interval(2500).pipe(
    take(5)
)

console.log(`${new Date().toLocaleTimeString()}: withLatestFrom start`)
source1$.pipe(
    withLatestFrom(source2$)
).subscribe({
    next: val =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: withLatestFrom`, val)
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;15:44:11: withLatestFrom start
15:44:14: withLatestFrom [ 2, 0 ]
15:44:15: withLatestFrom [ 3, 0 ]
15:44:16: withLatestFrom [ 4, 1 ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok guys, that&apos;s all for today!
You can find the code of this article &lt;a href=&quot;https://github.com/Puppo/rxjs-getting-started/tree/08-join-operators&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See you soon!&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Transformation Operators</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-transformation-operators/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-transformation-operators/</guid><description>Welcome back, Today I&apos;ll speak about the Transformation Operators. These operators are used to modify...</description><pubDate>Mon, 20 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome back,
Today I&apos;ll speak about the Transformation Operators. These operators are used to modify the value received.
But cut the chatter, and let&apos;s start.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/map&quot;&gt;map&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Applies a given project function to each value emitted by the source Observable, and emits the resulting values as an Observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval } from &apos;rxjs&apos;;
import { map, take, tap } from &apos;rxjs/operators&apos;;

const source$ = interval(1000, ).pipe(
    take(5),
    tap(val =&amp;gt; {
        console.log(`${new Date().toLocaleTimeString()}: Generated`, val);
    }),
)

source$.pipe(
    map(value =&amp;gt; Math.pow(value, 2))
)
.subscribe({
    next: value =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: map`, value),
    complete: () =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: map: complete`),
})
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;16:58:51: Generated 0
16:58:51: map 0
16:58:52: Generated 1
16:58:52: map 1
16:58:53: Generated 2
16:58:53: map 4
16:58:54: Generated 3
16:58:54: map 9
16:58:55: Generated 4
16:58:55: map 16
16:58:55: map: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The map operator is like the map function of the arrays.
It transforms the value using the function passed as an argument.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/mapTo&quot;&gt;mapTo&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Emits the given constant value on the output Observable every time the source Observable emits a value.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval } from &apos;rxjs&apos;;
import { mapTo, take, tap } from &apos;rxjs/operators&apos;;

const source1$ = interval(1000).pipe(
    take(5),
    tap(val =&amp;gt; {
        console.log(`${new Date().toLocaleTimeString()}: Source1 Generated`, val);
    }),
)

console.log(`${new Date().toLocaleTimeString()}: mapTo: start`)
source1$.pipe(
    mapTo(1000)
)
.subscribe({
    next: value =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: mapTo`, value),
    complete: () =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: mapTo: complete`),
})
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;17:03:01: mapTo: start
17:03:02: Source1 Generated 0
17:03:02: mapTo 1000
17:03:03: Source1 Generated 1
17:03:03: mapTo 1000
17:03:04: Source1 Generated 2
17:03:04: mapTo 1000
17:03:05: Source1 Generated 3
17:03:05: mapTo 1000
17:03:06: Source1 Generated 4
17:03:06: mapTo 1000
17:03:06: mapTo: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The operator is similar to the map operator, but it returns a fixed value that does not depend on the source.&lt;/p&gt;
&lt;p&gt;Now I start to talk about the operators: concat, exhaust, merge and switch.
These operators are similar to the others but they have some minimum differences that change their behaviour, and if you choose the wrong implementations you may not have the aspected result.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/concatMap&quot;&gt;concatMap&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Projects each source value to an Observable which is merged in the output Observable, in a serialized fashion waiting for each one to complete before merging the next.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval, Observable, of } from &apos;rxjs&apos;;
import { concatMap, delay, take, tap } from &apos;rxjs/operators&apos;;

const powWithDelay$ = (value: number): Observable&amp;lt;number&amp;gt; =&amp;gt; of(Math.pow(value, 2)).pipe(delay(2000))

const source$ = interval(1000).pipe(
    take(5),
    tap(val =&amp;gt; {
        console.log(`${new Date().toLocaleTimeString()}: Generated`, val);
    }),
)

source$.pipe(
    concatMap(value =&amp;gt; powWithDelay$(value))
)
.subscribe({
    next: value =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: concatMap`, value),
    complete: () =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: concatMap: complete`),
})
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;17:54:07: Generated 0
17:54:08: Generated 1
17:54:09: Generated 2
17:54:09: concatMap 0
17:54:10: Generated 3
17:54:11: Generated 4
17:54:11: concatMap 1
17:54:13: concatMap 4
17:54:15: concatMap 9
17:54:17: concatMap 16
17:54:17: concatMap: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator is used to concatenate different observables.
The first source starts to emit the values, and the concatMap operator runs another observable for every value. The result values of the last observables are emitted as results of the operator concat.
You should remember that the concatMap operator runs only one value at a time. You can notice from the previous examples that the values 0,1 and 2 are emitted before the result of the first concatMap (0), and after that, you can notice the emission of the values 3 and 4 before the result of the second emitted value. The particular behaviour of the concatMap operator is better visible after the last generated value from the first source (4) because we can see all the concatMap results emitted every 2 seconds from each other.&lt;/p&gt;
&lt;p&gt;Here&apos;s the marble diagram to explain better the behaviour:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/concatMapTo&quot;&gt;concatMapTo&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Projects each source value to the same Observable which is merged multiple times in a serialized fashion on the output Observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval } from &apos;rxjs&apos;;
import { concatMapTo, skip, take, tap } from &apos;rxjs/operators&apos;;

const source1$ = interval(1000, ).pipe(
    skip(2),
    take(2),
    tap(val =&amp;gt; {
        console.log(`${new Date().toLocaleTimeString()}: Source1 Generated`, val);
    }),
)

const source2$ = interval(2000, ).pipe(
    take(2),
    tap(val =&amp;gt; {
        console.log(`${new Date().toLocaleTimeString()}: Source2 Generated`, val);
    }),
)

console.log(`${new Date().toLocaleTimeString()}: concatMapTo: start`)
source1$.pipe(
    concatMapTo(source2$)
)
.subscribe({
    next: value =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: concatMapTo`, value),
    complete: () =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: concatMapTo: complete`),
})
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;18:12:28: concatMapTo: start
18:12:31: Source1 Generated 2
18:12:32: Source1 Generated 3
18:12:33: Source2 Generated 0
18:12:33: concatMapTo 0
18:12:35: Source2 Generated 1
18:12:35: concatMapTo 1
18:12:37: Source2 Generated 0
18:12:37: concatMapTo 0
18:12:39: Source2 Generated 1
18:12:39: concatMapTo 1
18:12:39: concatMapTo: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator is like the concatMap apart from the fact that it returns another observable that does not depend on the value received.
It can be used when an observable emit a value and we need to run another observable.
For example, we have a source that is a timer, and on every tick, we need to call an API. If we use the concatMapTo we can implement this solution easier.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/exhaustMap&quot;&gt;exhaustMap&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Projects each source value to an Observable which is merged in the output Observable only if the previous projected Observable has completed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval, Observable, of } from &apos;rxjs&apos;;
import { delay, exhaustMap, take, tap } from &apos;rxjs/operators&apos;;

const powWithDelay$ = (value: number): Observable&amp;lt;number&amp;gt; =&amp;gt; of(Math.pow(value, 2)).pipe(delay(2000))

const source$ = interval(1000, ).pipe(
    take(5),
    tap(val =&amp;gt; {
        console.log(`${new Date().toLocaleTimeString()}: Generated`, val);
    }),
)

source$.pipe(
    exhaustMap(value =&amp;gt; powWithDelay$(value))
)
.subscribe({
    next: value =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: exhaustMap`, value),
    complete: () =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: exhaustMap: complete`),
})
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;18:17:47: Generated 0
18:17:48: Generated 1
18:17:49: Generated 2
18:17:49: exhaustMap 0
18:17:50: Generated 3
18:17:51: Generated 4
18:17:52: exhaustMap 9
18:17:52: exhaustMap: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The exhaustMap operator syntactically is equal to the concat operator, but it has a different behavior: this operator during the execution of a projection ignores all other values received until the execution is not ended. If you see the result in the console of the before example, you can notice that the power of the values 1, 2, and 4 has never been shown.&lt;/p&gt;
&lt;p&gt;The marble diagram of the exhaustMap operator in the previous example:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/mergeMap&quot;&gt;mergeMap&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Projects each source value to an Observable which is merged in the output Observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval, Observable, of } from &apos;rxjs&apos;;
import { delay, mergeMap, take, tap } from &apos;rxjs/operators&apos;;

const powWithDelay$ = (value: number): Observable&amp;lt;number&amp;gt; =&amp;gt; of(Math.pow(value, 2)).pipe(delay(2000))

const source$ = interval(1000, ).pipe(
    take(5),
    tap(val =&amp;gt; {
        console.log(`${new Date().toLocaleTimeString()}: Generated`, val);
    }),
)

source$.pipe(
    mergeMap(value =&amp;gt; powWithDelay$(value))
)
.subscribe({
    next: value =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: mergeMap`, value),
    complete: () =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: mergeMap: complete`),
})
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;18:18:16: Generated 0
18:18:17: Generated 1
18:18:18: Generated 2
18:18:18: mergeMap 0
18:18:19: mergeMap 1
18:18:19: Generated 3
18:18:20: mergeMap 4
18:18:20: Generated 4
18:18:21: mergeMap 9
18:18:22: mergeMap 16
18:18:22: mergeMap: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The mergeMap operator is syntactically like concat and exhaust but it executes the projection as soon as a value arrives. This behaviour can open some strange cases, for example, it&apos;s not guaranteed the order of the result values with the order of the source values.
Let me give an example: we have a source that emits some values every 500ms, in the mergeMap operator we call an http API; the first value calls the API and the response arrives after 1.5seconds, the second value calls the same api but the response arrives after 200ms. The mergeMap operator in this case emits the result of the second value primarily and the result of the first one secondly.
As you can imagine, in some cases this behaviour can be wrong or unexpected, so, if you need to use the mergeMap operator, remember what I said before and ask yourself if it can produce some side effects or if it is the right solution of your problems.&lt;/p&gt;
&lt;p&gt;Here is the MergeMap marble Diagram of the previous example:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/mergeMapTo&quot;&gt;mergeMapTo&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Projects each source value to the same Observable which is merged multiple times in the output Observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval } from &apos;rxjs&apos;;
import { mergeMapTo, skip, take, tap } from &apos;rxjs/operators&apos;;

const source1$ = interval(1000, ).pipe(
    skip(2),
    take(2),
    tap(val =&amp;gt; {
        console.log(`${new Date().toLocaleTimeString()}: Source1 Generated`, val);
    }),
)

const source2$ = interval(2000, ).pipe(
    take(2),
    tap(val =&amp;gt; {
        console.log(`${new Date().toLocaleTimeString()}: Source2 Generated`, val);
    }),
)

console.log(`${new Date().toLocaleTimeString()}: mergeMap: start`)
source1$.pipe(
    mergeMapTo(source2$)
)
.subscribe({
    next: value =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: mergeMap`, value),
    complete: () =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: mergeMap: complete`),
})
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;18:18:53: mergeMap: start
18:18:56: Source1 Generated 2
18:18:57: Source1 Generated 3
18:18:58: Source2 Generated 0
18:18:58: mergeMap 0
18:18:59: Source2 Generated 0
18:18:59: mergeMap 0
18:19:00: Source2 Generated 1
18:19:00: mergeMap 1
18:19:01: Source2 Generated 1
18:19:01: mergeMap 1
18:19:01: mergeMap: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator is like the mergeMap apart from the fact that it returns another observable that does not depend on the value received.
It can be used when an observable emits a value and we need to run another observable.
In simple words, it&apos;s like the concatMapTo with the behaviour of the mergeMap operator behind the scene.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/switchMap&quot;&gt;switchMap&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Projects each source value to an Observable which is merged in the output Observable, emitting values only from the most recently projected Observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval, Observable, of } from &apos;rxjs&apos;;
import { delay, switchMap, take, tap } from &apos;rxjs/operators&apos;;

const powWithDelay$ = (value: number): Observable&amp;lt;number&amp;gt; =&amp;gt; of(Math.pow(value, 2)).pipe(delay(2000))

const source$ = interval(1000, ).pipe(
    take(5),
    tap(val =&amp;gt; {
        console.log(`${new Date().toLocaleTimeString()}: Generated`, val);
    }),
)

source$.pipe(
    switchMap(value =&amp;gt; powWithDelay$(value))
)
.subscribe({
    next: value =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: switchMap`, value),
    complete: () =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: switchMap: complete`),
})
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;18:19:16: Generated 0
18:19:17: Generated 1
18:19:18: Generated 2
18:19:19: Generated 3
18:19:20: Generated 4
18:19:22: switchMap 16
18:19:22: switchMap: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The switchMap operator is syntactically like concat, exhaust and merge. It executes the projection as soon as a value arrives, but when a new value arrives, if the projection of the previous value is in execution, it kills it and starts the execution of the projection for the new value.
It can be used for example for searching the data of an autocomplete input. When the user types a new letter and emits a new value, with this operator we can stop the previous search if it&apos;s on execution and start the new one.&lt;/p&gt;
&lt;p&gt;Here is the SwitchMap marble Diagram of the previous example:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/switchMapTo&quot;&gt;switchMapTo&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Projects each source value to the same Observable which is flattened multiple times with switchMap in the output Observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval } from &apos;rxjs&apos;;
import { skip, switchMapTo, take, tap } from &apos;rxjs/operators&apos;;

const source1$ = interval(1000, ).pipe(
    skip(2),
    take(2),
    tap(val =&amp;gt; {
        console.log(`${new Date().toLocaleTimeString()}: Source1 Generated`, val);
    }),
)

const source2$ = interval(2000, ).pipe(
    take(2),
    tap(val =&amp;gt; {
        console.log(`${new Date().toLocaleTimeString()}: Source2 Generated`, val);
    }),
)

console.log(`${new Date().toLocaleTimeString()}: switchMap: start`)
source1$.pipe(
    switchMapTo(source2$)
)
.subscribe({
    next: value =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: switchMap`, value),
    complete: () =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: switchMap: complete`),
})
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;18:19:38: switchMap: start
18:19:41: Source1 Generated 2
18:19:42: Source1 Generated 3
18:19:44: Source2 Generated 0
18:19:44: switchMap 0
18:19:46: Source2 Generated 1
18:19:46: switchMap 1
18:19:46: switchMap: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator is like the switchMap apart from the fact that it returns another observable that does not depend on the value received.
It can be used when an observable emits a value and we need to run another observable.
In simple words, it&apos;s like the concatMapTo or the mergeMapTo with the behaviour of the switchMap operator behind the scene.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;with this operator, we have finish the explanation of the 4 &quot;special&quot; operators (concat, exhaust, merge and switch). As you can see they are similar to each other but if you choose the wrong one it can produces some unexpected side effects.
I hope these examples can help you in future to choose the right operator for you&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/pairwise&quot;&gt;pairwise&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Groups pairs of consecutive emissions together and emits them as an array of two values.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { of } from &apos;rxjs&apos;;
import { pairwise } from &apos;rxjs/operators&apos;;

const source$ = of(1, 2, 3, 4, 5);

source$.pipe(
    pairwise()
)
.subscribe({
    next: value =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: pairwise`, value),
})
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;18:20:02: pairwise [ 1, 2 ]
18:20:02: pairwise [ 2, 3 ]
18:20:02: pairwise [ 3, 4 ]
18:20:02: pairwise [ 4, 5 ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator is used to get as result a tuple where in the first index there is the previous value and in the second index there is the current value. As you can imagine, if your source emits only one value the pairwise operator will never emit a value.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/scan&quot;&gt;scan&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Useful for encapsulating and managing state. Applies an accumulator (or &quot;reducer function&quot;) to each value from the source after an initial state is established -- either via a seed value (second argument), or from the first value from the source.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { of } from &apos;rxjs&apos;;
import { scan } from &apos;rxjs/operators&apos;;

const source$ = of(1, 2, 3, 4, 5);

source$.pipe(
    scan((acc, curr) =&amp;gt; acc + curr, 0)
)
.subscribe({
    next: value =&amp;gt; console.log(`${new Date().toLocaleTimeString()}: scan`, value),
})
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;18:20:26: scan 1
18:20:26: scan 3
18:20:26: scan 6
18:20:26: scan 10
18:20:26: scan 15
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator is similar to the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce&quot;&gt;reduce&lt;/a&gt; method of the array. We can create an accumulator and every time a new value is emitted from the source we can update this accumulator and return it as result.&lt;/p&gt;
&lt;p&gt;Ok, that&apos;s all from the Transformation Operators, I hope this examples can help you in future and I hope you have achieved a clear idea of how and when to use these operators.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Puppo/rxjs-getting-started/tree/07-transformation-operators&quot;&gt;in the GitHub repository&lt;/a&gt; you can find all the code examples.&lt;/p&gt;
&lt;p&gt;See you soon Guys
Bye Bye!&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Filtering Operators</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-filtering-operators/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-filtering-operators/</guid><description>Welcome back Guys, Today we&apos;ll start with the Filtering Operators. As you can imagine these...</description><pubDate>Fri, 17 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome back Guys,&lt;/p&gt;
&lt;p&gt;Today we&apos;ll start with the Filtering Operators. As you can imagine these operators are used to filter our sources.
Well, let&apos;s get started.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/auditTime&quot;&gt;auditTime&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Ignores source values for duration milliseconds, then emits the most recent value from the source Observable, then repeats this process.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { auditTime } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count &amp;lt; 10) {
      subscriber.next(++count);
    } else {
      clearInterval(id);
      subscriber.complete();
    }
  }, 1000);
});

const result = input$.pipe(auditTime(2000));

result.subscribe({
  next: x =&amp;gt;
    console.log(
      `${new Date().toLocaleTimeString()} - [auditTime result]: ${x}`
    ),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;11:15:25 - [auditTime result]: 2
11:15:27 - [auditTime result]: 4
11:15:29 - [auditTime result]: 6
11:15:31 - [auditTime result]: 8
11:15:33 - [auditTime result]: 10
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is particular: for the indicated time it ignores the emitted values, and when the time is passed, it emits the last value emitted from the source. It can be used when we have a source that emits a lot of values but we need to get only the value in a specific interval, for example, we have a temperature sensor that emits the temperature every second but we need to take the value every minute, using auditTime we can get the last value of every minute.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/debounceTime&quot;&gt;debounceTime&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Emits a notification from the source Observable only after a particular time span has passed without another source emission.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { debounceTime, tap } from &quot;rxjs/operators&quot;;

const timesInSecond = [1, 0.5, 3, 1.5, 3, 1];

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  (function next() {
    const seconds = timesInSecond[count++];
    setTimeout(() =&amp;gt; {
      subscriber.next(seconds);

      if (count &amp;gt; 5) {
        subscriber.complete();
        return;
      }

      next();
    }, seconds * 1000);
  })();
});

const result = input$.pipe(
  tap(x =&amp;gt;
    console.log(
      `${new Date().toLocaleTimeString()} - [before debounceTime]: ${x}`
    )
  ),
  debounceTime(2000)
);
result.subscribe({
  next: x =&amp;gt;
    console.log(
      `${new Date().toLocaleTimeString()} - [debounceTime result]: ${x}`
    ),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;09:44:29 - [before debounceTime]: 1
09:44:29 - [before debounceTime]: 0.5
09:44:31 - [debounceTime result]: 0.5
09:44:32 - [before debounceTime]: 3
09:44:34 - [before debounceTime]: 1.5
09:44:36 - [debounceTime result]: 1.5
09:44:37 - [before debounceTime]: 3
09:44:38 - [before debounceTime]: 1
09:44:38 - [debounceTime result]: 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
After receiving a value, this operator waits for the indicated time before emitting the value. If during this time a new value is emitted, the operator ignores the previous value and waits again, otherwise, if nothing happens it emits the value.
For example, this operator is used to manage the autocomplete text boxes that search items from an API; with this operator, we can prevent calling the API on every click on the keyboard but we can wait until the user finish writing some letters before executing the search.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/throttleTime&quot;&gt;throttleTime&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Emits a value from the source Observable, then ignores subsequent source values for duration milliseconds, then repeats this process.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { tap, throttleTime } from &quot;rxjs/operators&quot;;

const timesInSecond = [1, 0.5, 3, 1.5, 3, 1];

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  (function next() {
    const seconds = timesInSecond[count++];
    setTimeout(() =&amp;gt; {
      subscriber.next(seconds);

      if (count &amp;gt; 5) {
        subscriber.complete();
        return;
      }

      next();
    }, seconds * 1000);
  })();
});


const result = input$.pipe(
  tap(x =&amp;gt;
    console.log(
      `${new Date().toLocaleTimeString()} - [before throttleTime]: ${x}`
    )
  ),
  throttleTime(2000)
);
result.subscribe({
  next: x =&amp;gt;
    console.log(
      `${new Date().toLocaleTimeString()} - [throttleTime result]: ${x}`
    ),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10:41:46 - [before throttleTime]: 1
10:41:46 - [throttleTime result]: 1
10:41:46 - [before throttleTime]: 0.5
10:41:49 - [before throttleTime]: 3
10:41:49 - [throttleTime result]: 3
10:41:51 - [before throttleTime]: 1.5
10:41:54 - [before throttleTime]: 3
10:41:54 - [throttleTime result]: 3
10:41:55 - [before throttleTime]: 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
After receiving a value, this operator emits it and then waits for the indicated time. If during that time the source emits other values this operator ignores them, it repeats this process for life.
This operator is commonly used to prevent multiple clicks in some buttons or to prevent many executions of an action in a small period.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/distinct&quot;&gt;distinct&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns an Observable that emits all items emitted by the source Observable that are distinct by comparison from previous items.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { distinct } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number | string&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const array = [1, 1, &quot;1&quot;, 2, 2, 3, 3];
  const id = setInterval(() =&amp;gt; {
    if (count &amp;lt; array.length) {
      subscriber.next(array[count++]);
    } else {
      clearInterval(id);
      subscriber.complete();
    }
  }, 1000);
});

input$.pipe(distinct()).subscribe({
  next: x =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [distinct]: ${x}`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;12:22:58 - [distinct]: 1
12:23:00 - [distinct]: 1
12:23:01 - [distinct]: 2
12:23:03 - [distinct]: 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator emits the value only if the value is different from the last value emitted. It&apos;s important to remember that the distinct operator checks the equality using the strict equal operator (===). It&apos;s also possible, if your source emits an object, to indicate the property used to check the equality &lt;code&gt;distinct(p =&amp;gt; p.id)&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/distinctUntilChanged&quot;&gt;distinctUntilChanged&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { distinctUntilChanged } from &quot;rxjs/operators&quot;;

type State = { id: number; value: string };

const createValue = (id: number): State =&amp;gt; ({ id, value: String(id) });
const array = [
  createValue(1),
  createValue(1),
  createValue(1),
  createValue(2),
  createValue(2),
  createValue(2),
  createValue(3),
  createValue(3),
  createValue(3),
  createValue(4),
  createValue(4),
  createValue(4),
];

const input$ = new Observable&amp;lt;State&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count &amp;lt; array.length) {
      subscriber.next(array[count++]);
    } else {
      clearInterval(id);
      subscriber.complete();
    }
  }, 1000);
});

input$
  .pipe(distinctUntilChanged((prev, curr) =&amp;gt; prev.id === curr.id))
  .subscribe({
    next: x =&amp;gt;
      console.log(
        `${new Date().toLocaleTimeString()} - [distinctUntilChanged]`,
        x
      ),
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;11:45:39 - [distinctUntilChanged] { id: 1, value: &apos;1&apos; }
11:45:42 - [distinctUntilChanged] { id: 2, value: &apos;2&apos; }
11:45:45 - [distinctUntilChanged] { id: 3, value: &apos;3&apos; }
11:45:48 - [distinctUntilChanged] { id: 4, value: &apos;4&apos; }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is similar to the distinct operator but you can indicate a function that accepts the previous and the current item as arguments and indicates the algorithm to determinate if the two items are equals.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/distinctUntilKeyChanged&quot;&gt;distinctUntilKeyChanged&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns an Observable that emits all items emitted by the source Observable that are distinct by comparison from the previous item, using a property accessed by using the key provided to check if the two items are distinct.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { distinctUntilKeyChanged } from &quot;rxjs/operators&quot;;

type State = { id: number; value: string };

const createValue = (id: number): State =&amp;gt; ({ id, value: String(id) });
const array = [
  createValue(1),
  createValue(1),
  createValue(1),
  createValue(2),
  createValue(2),
  createValue(2),
  createValue(3),
  createValue(3),
  createValue(3),
  createValue(4),
  createValue(4),
  createValue(4),
];

const input$ = new Observable&amp;lt;State&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count &amp;lt; array.length) {
      subscriber.next(array[count++]);
    } else {
      clearInterval(id);
      subscriber.complete();
    }
  }, 1000);
});

input$.pipe(distinctUntilKeyChanged(&quot;id&quot;)).subscribe({
  next: x =&amp;gt;
    console.log(
      `${new Date().toLocaleTimeString()} - [distinctUntilKeyChanged]`,
      x
    ),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;11:46:12 - [distinctUntilKeyChanged] { id: 1, value: &apos;1&apos; }
11:46:15 - [distinctUntilKeyChanged] { id: 2, value: &apos;2&apos; }
11:46:18 - [distinctUntilKeyChanged] { id: 3, value: &apos;3&apos; }
11:46:21 - [distinctUntilKeyChanged] { id: 4, value: &apos;4&apos; }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is similar to the distinct operator but you can indicate the name of the property used to compare the equality.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/filter&quot;&gt;filter&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Filter items emitted by the source Observable by only emitting those that satisfy a specified predicate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { filter } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count &amp;lt; 10) {
      subscriber.next(++count);
    } else {
      clearInterval(id);
      subscriber.complete();
    }
  }, 1000);
});

input$.pipe(filter(x =&amp;gt; x % 2 === 0)).subscribe({
  next: x =&amp;gt; console.log(`${new Date().toLocaleTimeString()} - [filter]: ${x}`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;11:46:43 - [filter]: 2
11:46:45 - [filter]: 4
11:46:47 - [filter]: 6
11:46:49 - [filter]: 8
11:46:51 - [filter]: 10
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
As you can imagine, this operator accepts a function that has an argument (the current item) and returns a boolean that indicates if the value can be emitted or must be ignored.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/first&quot;&gt;first&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Emits only the first value (or the first value that meets some condition) emitted by the source Observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { first } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count &amp;lt; 10) {
      subscriber.next(++count);
    } else {
      clearInterval(id);
      subscriber.complete();
    }
  }, 1000);
});

console.log(`${new Date().toLocaleTimeString()} - [first] start`)
input$.pipe(first()).subscribe({
  next: x =&amp;gt; console.log(`${new Date().toLocaleTimeString()} - [first]: ${x}`),
  complete: () =&amp;gt; console.log(`${new Date().toLocaleTimeString()} - [first] complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;09:47:15 - [first] start
09:47:16 - [first]: 1
09:47:16 - [first] complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator takes the first value and ignores the others.
It&apos;s important to remember that when the first operator emits the value it completes the subscription too.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/last&quot;&gt;last&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns an Observable that emits only the last item emitted by the source Observable. It optionally takes a predicate function as a parameter, in which case, rather than emitting the last item from the source Observable, the resulting Observable will emit the last item from the source Observable that satisfies the predicate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { last } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count &amp;lt; 10) {
      subscriber.next(++count);
    } else {
      clearInterval(id);
      subscriber.complete();
    }
  }, 1000);
});

console.log(`${new Date().toLocaleTimeString()} - [last] start`)
input$.pipe(last()).subscribe({
  next: x =&amp;gt; console.log(`${new Date().toLocaleTimeString()} - [last]: ${x}`),
  complete: () =&amp;gt; console.log(`${new Date().toLocaleTimeString()} - [last] complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;09:48:14 - [last] start
09:48:25 - [last]: 10
09:48:25 - [last] complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator takes the last value and ignores the others.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/skip&quot;&gt;skip&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns an Observable that skips the first count items emitted by the source Observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { skip } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if(count &amp;lt; 5) subscriber.next(count++);
    else {
      clearInterval(id);
      subscriber.complete();
    } 
  }, 1000);
  return () =&amp;gt; {
    clearInterval(id);
    subscriber.complete();
  };
});

input$.pipe(skip(2)).subscribe({
  next: x =&amp;gt; console.log(`${new Date().toLocaleTimeString()} - [skip]: ${x}`),
  complete: () =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [skip]: complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10:33:41 - [skip]: 2
10:33:42 - [skip]: 3
10:33:43 - [skip]: 4
10:33:44 - [skip]: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
As you can see, this operator skips the first x items we indicate, if we write &lt;code&gt;skip(1)&lt;/code&gt; the operator skips the first value, if we write &lt;code&gt;skip(2)&lt;/code&gt; the operator skips the first two values and so on.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/skipLast&quot;&gt;skipLast&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Skip a specified number of values before the completion of an observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { skipLast } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count &amp;lt; 5) subscriber.next(count++);
    else {
      clearInterval(id);
      subscriber.complete();
    }
  }, 1000);
});

console.log(`${new Date().toLocaleTimeString()} - [skipLast]: start`)

input$.pipe(skipLast(3)).subscribe({
  next: x =&amp;gt; console.log(`${new Date().toLocaleTimeString()} - [skipLast]: ${x}`),
  complete: () =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [skipLast]: complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10:33:58 - [skipLast]: start
10:34:02 - [skipLast]: 0
10:34:03 - [skipLast]: 1
10:34:04 - [skipLast]: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator skips the last x items we indicate, if we write &lt;code&gt;skipLast(1)&lt;/code&gt; the operator skips the last value, if we write &lt;code&gt;skipLast(2)&lt;/code&gt; the operator skips the last two values and so on.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/skipUntil&quot;&gt;skipUntil&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns an Observable that skips items emitted by the source Observable until a second Observable emits an item.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { skipUntil } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count &amp;lt; 5) subscriber.next(count++)
    else {
      clearInterval(id);
      subscriber.complete();
    }
  }, 1000);
});

const untilInput$ = new Observable&amp;lt;void&amp;gt;(subscriber =&amp;gt; {
  setTimeout(() =&amp;gt; {
    console.log(
      `${new Date().toLocaleTimeString()} - untilInput$ emit`
    );
    subscriber.next();
    subscriber.complete();
  }, 5000);
});

input$.pipe(skipUntil(untilInput$)).subscribe({
  next: x =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [skipUntil]: ${x}`),
  complete: () =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [skipUntil]: complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10:34:37 - untilInput$ emit
10:34:37 - [skipUntil]: 4
10:34:38 - [skipUntil]: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator skips all the values until another observable doesn&apos;t emit a value.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/skipWhile&quot;&gt;skipWhile&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns an Observable that skips all items emitted by the source Observable as long as a specified condition holds true, but emits all further source items as soon as the condition becomes false.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { skipWhile } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count &amp;lt; 5) subscriber.next(count++);
    else {
      subscriber.next(count++);
      subscriber.complete();
    }
  }, 1000);
  return () =&amp;gt; {
    clearInterval(id);
  };
});

input$.pipe(skipWhile(val =&amp;gt; val &amp;lt; 3)).subscribe({
  next: x =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [skipWhile]: ${x}`),
  complete: () =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [skipWhile]: complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10:36:34 - [skipWhile]: 3
10:36:35 - [skipWhile]: 4
10:36:36 - [skipWhile]: 5
10:36:36 - [skipWhile]: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator skips all the values ​​until the predicate isn&apos;t true, after the first true result, the skipWhile operator doesn&apos;t eval anymore the predicate and emits all the values.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/take&quot;&gt;take&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Emits only the first count values emitted by the source Observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { take } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    subscriber.next(count++);
  }, 1000);
  return () =&amp;gt; {
    clearInterval(id);
    subscriber.complete();
  };
});

input$.pipe(take(2)).subscribe({
  next: x =&amp;gt; console.log(`${new Date().toLocaleTimeString()} - [take]: ${x}`),
  complete: () =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [take]: complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10:39:39 - [take]: 0
10:39:40 - [take]: 1
10:39:40 - [take]: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
The take operator is the opposite of the skip operator, if the skip ignores x values, the take operator emits x values.
So if you write &lt;code&gt;take(1)&lt;/code&gt; you get only the first value, if you write &lt;code&gt;take(2)&lt;/code&gt; you get only the first two values.
It&apos;s important to remember that when the operator emits the last value completes the subscription too.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/takeLast&quot;&gt;takeLast&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Waits for the source to complete, then emits the last N values from the source, as specified by the count argument.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { takeLast } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count &amp;lt; 5) subscriber.next(count++);
    else {
      clearInterval(id);
      subscriber.complete();
    }
  }, 1000);
});

console.log(`${new Date().toLocaleTimeString()} - [takeLast]: start`)

input$.pipe(takeLast(3)).subscribe({
  next: x =&amp;gt; console.log(`${new Date().toLocaleTimeString()} - [takeLast]: ${x}`),
  complete: () =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [takeLast]: complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10:40:08 - [takeLast]: start
10:40:14 - [takeLast]: 2
10:40:14 - [takeLast]: 3
10:40:14 - [takeLast]: 4
10:40:14 - [takeLast]: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator takes the last x items we indicate, if we write takeLast(1) the operator takes the last value, if we write takeLast(3) the operator takes the last three values, and so on.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/takeUntil&quot;&gt;takeUntil&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Emits the values emitted by the source Observable until a notifier Observable emits a value.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { takeUntil } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count &amp;lt; 5) subscriber.next(++count);
    else {
      clearInterval(id);
      subscriber.complete();
    }
  }, 1000);
});

const untilInput$ = new Observable&amp;lt;void&amp;gt;(subscriber =&amp;gt; {
  setTimeout(() =&amp;gt; {
    console.log(
      `${new Date().toLocaleTimeString()} - untilInput$ emit`
    );
    subscriber.next();
    subscriber.complete();
  }, 2500);
});

input$.pipe(takeUntil(untilInput$)).subscribe({
  next: x =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [takeUntil]: ${x}`),
  complete: () =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [takeUntil]: complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10:40:38 - [takeUntil]: 1
10:40:39 - [takeUntil]: 2
10:40:42 - untilInput$ emit
10:40:42 - [takeUntil]: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator takes all the values until another observable doesn&apos;t emit a value, after that it complete the subscription.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/operators/takeWhile&quot;&gt;takeWhile&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Emits values emitted by the source Observable so long as each value satisfies the given predicate, and then completes as soon as this predicate is not satisfied.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { takeWhile } from &quot;rxjs/operators&quot;;

const input$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    subscriber.next(count++);
  }, 1000);
  return () =&amp;gt; {
    clearInterval(id);
    subscriber.complete();
  };
});

input$.pipe(takeWhile(val =&amp;gt; val &amp;lt; 3)).subscribe({
  next: x =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [takeWhile]: ${x}`),
  complete: () =&amp;gt;
    console.log(`${new Date().toLocaleTimeString()} - [takeWhile]: complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;10:41:10 - [takeWhile]: 0
10:41:11 - [takeWhile]: 1
10:41:12 - [takeWhile]: 2
10:41:13 - [takeWhile]: complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator emits all the values ​​until the predicate is true, after that the takeWhile operator completes the subscription.&lt;/p&gt;
&lt;p&gt;Ok Guys, I think that today it&apos;s enough for the Filter Operators.
You can find all the code of this article &lt;a href=&quot;https://github.com/Puppo/rxjs-getting-started/tree/06-filtering-operators&quot;&gt;in the GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you in the next article.
Bye Bye!&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Creation Operators</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-creation-operators/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-creation-operators/</guid><description>Welcome back guys, today I&apos;ll start to show you the Creation operators in RxJS. The Creation...</description><pubDate>Wed, 15 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome back guys,
today I&apos;ll start to show you the Creation operators in RxJS.&lt;/p&gt;
&lt;p&gt;The Creation Operators are used to create new observables. They are divided into Creation Operators and Join Creation Operators.
The main difference between them consists in the fact that the Join Creation Operators create observable from other observables instead the Creation Operators create observables from objects which differ from observable.&lt;/p&gt;
&lt;h2&gt;&lt;a href=&quot;https://rxjs.dev/guide/operators#creation-operators-2&quot;&gt;Creation Operators&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/index/function/of&quot;&gt;of&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;The Of operator is used to convert an argument to an observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { of } from &quot;rxjs&quot;;

of([1, 2, 3], 4, 5, 6).subscribe({
  next: res =&amp;gt; console.log(&quot;[of]&quot;, res),
  complete: () =&amp;gt; console.log(&quot;[of] complete&quot;),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[of] [ 1, 2, 3 ]
[of] 4
[of] 5
[of] 6
[of] complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
As you can see, this operator takes a list of arguments and converts them to values of the observable.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/index/function/from&quot;&gt;from&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;This operator creates an Observable from an Array, an array-like object, a Promise, an iterable object, or an Observable-like object.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;from array&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from([1, 2, 3]).subscribe(res =&amp;gt; console.log(&quot;[from]&quot;, res));
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[from] 1
[from] 2
[from] 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
In this case we converted an array to an observable.
The from operator converts all the items in the array to values of the observable. It&apos;s common to use this operator when we need to convert the items of an array to the values to react our system.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;from promise&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from(
  new Promise(res =&amp;gt; setTimeout(() =&amp;gt; res(&quot;Hello from promise&quot;), 3000))
).subscribe(res =&amp;gt; console.log(new Date().toLocaleTimeString(), `[from]`, res));
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;13:47:52 [from] Hello from promise
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case we converted a promise to an observable. It is common to convert a promise to an observable, or because we have multiple subscribers which need to react to this promise or because we need to use these promise inside of a pipe chain.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;from iterator&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const wait = async (time: number) =&amp;gt; new Promise(res =&amp;gt; setTimeout(res, time));
async function* hello() {
  yield &quot;Hello&quot;;
  await wait(1000);
  yield &quot;from&quot;;
  await wait(1000);
  yield &quot;iterator&quot;;
}
from(hello()).subscribe({
  next: res =&amp;gt; console.log(new Date().toLocaleTimeString(), `[from]`, res),
  complete: () =&amp;gt;
    console.log(new Date().toLocaleTimeString(), `[from] complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;13:48:42 [from] Hello
13:48:43 [from] from
13:48:44 [from] iterator
13:48:44 [from] complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here instead, the from operator converts an iterator to an observable. This is common when we need to react to every item of the iterator or when we need to use the generator inside of a pipe chain.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/index/function/fromEvent&quot;&gt;fromEvent&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;The fromEvent operator is usage to emit an observable in base of an event&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Some examples: when a user clicks to a document element in HTML/JS or when a system emits an &lt;a href=&quot;https://nodejs.org/api/events.html&quot;&gt;event&lt;/a&gt; in node.js eco system.
Here a practise example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import * as events from &quot;events&quot;;
import { fromEvent } from &quot;rxjs&quot;;

console.log(new Date().toLocaleTimeString(), &quot;[fromEvent] start&quot;);

const em = new events.EventEmitter();
fromEvent(em, &quot;custom-event&quot;).subscribe({
  next: res =&amp;gt; console.log(new Date().toLocaleTimeString(), &quot;[fromEvent]&quot;, res),
  complete: () =&amp;gt;
    console.log(new Date().toLocaleTimeString(), &quot;[fromEvent] complete&quot;),
});

setTimeout(() =&amp;gt; {
  em.emit(&quot;custom-event&quot;, &quot;Hello from event emitter&quot;);
}, 3000);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;14:05:06 [fromEvent] start
14:05:09 [fromEvent] Hello from event emitter
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/index/const/EMPTY&quot;&gt;EMPTY&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Creates an Observable that emits no items to the Observer and immediately emits a complete notification.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { EMPTY } from &quot;rxjs&quot;;

EMPTY.subscribe({
  next: res =&amp;gt; console.log(&quot;[EMPTY]&quot;, res),
  complete: () =&amp;gt; console.log(&quot;[EMPTY] complete&quot;),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[EMPTY] complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is used for scheduling the emission of the complete notification.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/index/function/timer&quot;&gt;timer&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Creates an observable that will wait for a specified time period, or exact date, before emitting the number 0.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { timer } from &quot;rxjs&quot;;

console.log(new Date().toLocaleTimeString(), &quot;[timer] start&quot;);
timer(1000).subscribe({
  next: res =&amp;gt; console.log(new Date().toLocaleTimeString(), &quot;[timer]&quot;, res),
  complete: () =&amp;gt;
    console.log(new Date().toLocaleTimeString(), &quot;[timer] complete&quot;),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;14:14:34 [timer] start
14:14:35 [timer] 0
14:14:35 [timer] complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is similar to the setTimeout function in JS. It creates an observable and emits only a value after a time indicated as argument.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/index/function/interval&quot;&gt;interval&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Creates an Observable that emits sequential numbers every specified interval of time, on a specified SchedulerLike.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { interval } from &quot;rxjs&quot;;

console.log(new Date().toLocaleTimeString(), &quot;[interval] start&quot;);
interval(1000).subscribe({
  next: res =&amp;gt; console.log(new Date().toLocaleTimeString(), &quot;[interval]&quot;, res),
  complete: () =&amp;gt;
    console.log(new Date().toLocaleTimeString(), &quot;[interval] complete&quot;),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;14:15:10 [interval] start
14:15:11 [interval] 0
14:15:12 [interval] 1
14:15:13 [interval] 2
14:15:14 [interval] 3
14:15:15 [interval] 4
...
...
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is similar to the setInterval function in JS. It creates an observable and emits a sequential number every specific time indicated as argument.
&lt;em&gt;N.B. it start from ZERO and not from ONE&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;timer as special interval&lt;/strong&gt;
Sometimes you need to create an interval with a specific period but you need to start it with a period different from the interval period. In these cases it is common to use the timer operator that accepts a period as second argument.
So you can indicate the time before emitting the first value as first argument and the period of the interval as second argument.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;timer(1000, 1000).subscribe({
  next: res =&amp;gt;
    console.log(new Date().toLocaleTimeString(), &quot;[timer as interval]&quot;, res),
  complete: () =&amp;gt;
    console.log(
      new Date().toLocaleTimeString(),
      &quot;[timer as interval] complete&quot;
    ),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;14:25:56 [timer as interval] start
14:26:00 [timer as interval] 0
14:26:01 [timer as interval] 1
14:26:02 [timer as interval] 2
...
...
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;&lt;a href=&quot;https://rxjs.dev/guide/operators#join-creation-operators&quot;&gt;Join Creation Operators&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Before starting, I clarify that all the examples use these three observable as inputs.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { from, Observable } from &quot;rxjs&quot;;

async function* hello() {
  const wait = async (time: number) =&amp;gt;
    new Promise(res =&amp;gt; setTimeout(res, time));
  yield &quot;Hello&quot;;
  await wait(1000);
  yield &quot;from&quot;;
  await wait(500);
  yield &quot;iterator&quot;;
}

export const iterator$ = from(hello());
export const arrayFrom$ = from([&quot;Hello&quot;, &quot;from&quot;, &quot;array&quot;]);
export const arrayOfWithDelay$ = new Observable&amp;lt;number&amp;gt;(subscriber =&amp;gt; {
  let counter = 10;
  const id = setInterval(() =&amp;gt; {
    if (counter &amp;gt; 0) {
      subscriber.next(counter--);
    } else {
      clearInterval(id);
      subscriber.complete();
    }
  }, 500);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/index/function/combineLatest&quot;&gt;combineLatest&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Combines multiple Observables to create an Observable whose values are calculated from the latest values of each of its input Observables.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { combineLatest } from &quot;rxjs&quot;;
import { arrayFrom$, arrayOfWithDelay$, iterator$ } from &quot;../sources&quot;;

console.log(new Date().toLocaleTimeString(), `[combineLatest] start`);

combineLatest([iterator$, arrayFrom$, arrayOfWithDelay$]).subscribe({
  next: res =&amp;gt;
    console.log(new Date().toLocaleTimeString(), `[combineLatest]`, res),
  complete: () =&amp;gt;
    console.log(new Date().toLocaleTimeString(), `[combineLatest] complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;12:38:22 [combineLatest] start
12:38:22 [combineLatest] [ &apos;Hello&apos;, &apos;array&apos;, 10 ]
12:38:23 [combineLatest] [ &apos;from&apos;, &apos;array&apos;, 10 ]
12:38:23 [combineLatest] [ &apos;from&apos;, &apos;array&apos;, 9 ]
12:38:23 [combineLatest] [ &apos;iterator&apos;, &apos;array&apos;, 9 ]
12:38:23 [combineLatest] [ &apos;iterator&apos;, &apos;array&apos;, 8 ]
12:38:24 [combineLatest] [ &apos;iterator&apos;, &apos;array&apos;, 7 ]
12:38:24 [combineLatest] [ &apos;iterator&apos;, &apos;array&apos;, 6 ]
12:38:25 [combineLatest] [ &apos;iterator&apos;, &apos;array&apos;, 5 ]
12:38:25 [combineLatest] [ &apos;iterator&apos;, &apos;array&apos;, 4 ]
12:38:26 [combineLatest] [ &apos;iterator&apos;, &apos;array&apos;, 3 ]
12:38:26 [combineLatest] [ &apos;iterator&apos;, &apos;array&apos;, 2 ]
12:38:27 [combineLatest] [ &apos;iterator&apos;, &apos;array&apos;, 1 ]
12:38:27 [combineLatest] complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
In this example, you can see how this operator emits an array of value every time an observable emits one value.
It&apos;s important to remember that the operator emits the first value when all the dependence observables emit the first value.
As you can see, the result of the combineLatest operator is an array where items respect the order of the observables in the declaration.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/index/function/forkJoin&quot;&gt;forkJoin&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Accepts an Array of ObservableInput or a dictionary Object of ObservableInput and returns an Observable that emits either an array of values in the exact same order as the passed array, or a dictionary of values in the same shape as the passed dictionary.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { forkJoin } from &quot;rxjs&quot;;
import { arrayFrom$, arrayOfWithDelay$, iterator$ } from &quot;../sources&quot;;

console.log(new Date().toLocaleTimeString(), `[forkJoin] start`);

forkJoin([iterator$, arrayFrom$, arrayOfWithDelay$]).subscribe({
  next: res =&amp;gt; console.log(new Date().toLocaleTimeString(), `[forkJoin]`, res),
  complete: () =&amp;gt;
    console.log(new Date().toLocaleTimeString(), `[forkJoin] complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;14:38:58 [forkJoin] start
14:39:04 [forkJoin] [ &apos;iterator&apos;, &apos;array&apos;, 1 ]
14:39:04 [forkJoin] complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
forkJoin is similar to the combineLatest operator, the difference is that the forkJoin operator emits only one value when all the observables are completed. In simple words, the forkJoin operator emits only the last value of the combineLatest operator.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/index/function/concat&quot;&gt;concat&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Creates an output Observable which sequentially emits all values from the first given Observable and then moves on to the next.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { concat } from &quot;rxjs&quot;;
import { arrayFrom$, arrayOfWithDelay$, iterator$ } from &quot;../sources&quot;;

console.log(new Date().toLocaleTimeString(), `[concat] start`);

concat(iterator$, arrayFrom$, arrayOfWithDelay$).subscribe({
  next: res =&amp;gt; console.log(new Date().toLocaleTimeString(), `[concat]`, res),
  complete: () =&amp;gt;
    console.log(new Date().toLocaleTimeString(), `[concat] complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;14:44:23 [concat] start
14:44:23 [concat] Hello
14:44:24 [concat] from
14:44:24 [concat] iterator
14:44:24 [concat] Hello
14:44:24 [concat] from
14:44:24 [concat] array
14:44:25 [concat] 10
14:44:25 [concat] 9
14:44:26 [concat] 8
14:44:26 [concat] 7
14:44:27 [concat] 6
14:44:27 [concat] 5
14:44:28 [concat] 4
14:44:28 [concat] 3
14:44:29 [concat] 2
14:44:29 [concat] 1
14:44:30 [concat] complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
As you can see, this operator emits all the values of the observables in sequences.
Concat unlike of combineLatest does not run all observables in concurrency, but it runs the observables in sequence, it starts from the first and doesn&apos;t go to the next until the current is not completed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/index/function/merge&quot;&gt;merge&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Creates an output Observable which concurrently emits all values from every given input Observable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { merge } from &quot;rxjs&quot;;
import { arrayFrom$, arrayOfWithDelay$, iterator$ } from &quot;../sources&quot;;

console.log(new Date().toLocaleTimeString(), `[merge] start`);

merge(iterator$, arrayFrom$, arrayOfWithDelay$).subscribe({
  next: res =&amp;gt; console.log(new Date().toLocaleTimeString(), `[merge]`, res),
  complete: () =&amp;gt;
    console.log(new Date().toLocaleTimeString(), `[merge] complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;14:58:48 [merge] start
14:58:48 [merge] Hello
14:58:48 [merge] from
14:58:48 [merge] array
14:58:48 [merge] Hello
14:58:48 [merge] 10
14:58:49 [merge] from
14:58:49 [merge] 9
14:58:49 [merge] iterator
14:58:49 [merge] 8
14:58:50 [merge] 7
14:58:50 [merge] 6
14:58:51 [merge] 5
14:58:51 [merge] 4
14:58:52 [merge] 3
14:58:52 [merge] 2
14:58:53 [merge] 1
14:58:53 [merge] complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
The merge operator is similar to the concat operator unlike that the merge operator runs all observables in concurrency mode, so, in this case, all the observables start together and every time an observable emits a value the merge operator emits this last value.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/index/function/race&quot;&gt;race&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Returns an observable that mirrors the first source observable to emit an item.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { race } from &quot;rxjs&quot;;
import { arrayFrom$, arrayOfWithDelay$, iterator$ } from &quot;../sources&quot;;

console.log(new Date().toLocaleTimeString(), `[race] start`);

race([iterator$, arrayFrom$, arrayOfWithDelay$]).subscribe({
  next: res =&amp;gt; console.log(new Date().toLocaleTimeString(), `[race]`, res),
  complete: () =&amp;gt;
    console.log(new Date().toLocaleTimeString(), `[race] complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;15:09:03 [race] start
15:09:03 [race] Hello
15:09:03 [race] from
15:09:03 [race] array
15:09:03 [race] complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator is particular, it emits the first observable that emits the first value. In other words, it takes the faster observable and ignores the others.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://rxjs.dev/api/index/function/zip&quot;&gt;zip&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Combines multiple Observables to create an Observable whose values are calculated from the values, in order, of each of its input Observables.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;import { zip } from &quot;rxjs&quot;;
import { arrayFrom$, arrayOfWithDelay$, iterator$ } from &quot;../sources&quot;;

console.log(new Date().toLocaleTimeString(), `[zip] start`);

zip([iterator$, arrayFrom$, arrayOfWithDelay$]).subscribe({
  next: res =&amp;gt; console.log(new Date().toLocaleTimeString(), `[zip]`, res),
  complete: () =&amp;gt;
    console.log(new Date().toLocaleTimeString(), `[zip] complete`),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;15:09:27 [zip] start
15:09:27 [zip] [ &apos;Hello&apos;, &apos;Hello&apos;, 10 ]
15:09:28 [zip] [ &apos;from&apos;, &apos;from&apos;, 9 ]
15:09:28 [zip] [ &apos;iterator&apos;, &apos;array&apos;, 8 ]
15:09:28 [zip] complete
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
This operator may seem strange, but it can use to combine in order the values of difference observables.
In this example we have 3 observables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;iterator$: &lt;code&gt;[&apos;Hello&apos;, &apos;from&apos;, &apos;iterator&apos;, &apos;!&apos;]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;arrayFrom$: &lt;code&gt;[&apos;Hello&apos;, &apos;from&apos;, &apos;array&apos;, &apos;!&apos;]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;arrayOfWithDelay$: &lt;code&gt;[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the zip operator we combine the values in order of them index:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[&apos;Hello&apos;, &apos;Hello&apos;, 10]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[&apos;from&apos;, &apos;from&apos;, 9]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[&apos;iterator&apos;, &apos;array&apos;, 8]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can see, the operator stops emitting values at the index of the first completed observable.&lt;/p&gt;
&lt;p&gt;That&apos;s it for today.
You can find the code of these examples at this &lt;a href=&quot;https://github.com/Puppo/rxjs-getting-started/tree/05-creation-operators&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See you soon Guys!&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Marble Diagrams</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-marble-diagrams/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-marble-diagrams/</guid><description>Hi guy, before continuing with the operators, today I want to explain the Marble Diagrams. The Marble...</description><pubDate>Mon, 13 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi guy,
before continuing with the operators, today I want to explain the &lt;em&gt;Marble Diagrams&lt;/em&gt;.
The Marble Diagrams is a timeline where you can illustrate the state of your observable during its execution.
The actors in this diagram are timeline and values(circle).
The timeline is used to represent the time during the execution of the observable though the circles indicate the values emitted.
But let me show you an example:
&lt;/p&gt;
&lt;p&gt;This example is based on this code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { map } from &quot;rxjs/operators&quot;;

const source$ = new Observable&amp;lt;number&amp;gt;(observer =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count++ &amp;lt; 3) {
      observer.next(count);
    } else {
      clearInterval(id);
      observer.complete();
    }
  }, 1000);
});

source$.pipe(map(value =&amp;gt; value * 2)).subscribe({
  next: console.log,
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can notice, in the diagram there are two timelines, one for the source and the other for the map operator.
In the first timeline you can see when the source emits the value, in the second timeline you can see the result of the transformation after the execution of the map operator.&lt;/p&gt;
&lt;p&gt;To build a Marble diagram you need to keep in mind some easy rules: there is always a timeline that represents the source observable, there are N timelines as many operators as you need to display, every timeline illustrates the state of the values after the execution of the operator indicated in the timeline and finally, you need to use a circle to represent the values.&lt;/p&gt;
&lt;p&gt;This tool is very convenient to illustrate the transformation of the observable during its execution and it helps us to have an image of the state of the observable execution.&lt;/p&gt;
&lt;p&gt;In addition to the Marble Diagram you can use the Marble Testing to test the execution of you Observable.
The Marble testing uses a special format to represent the timeline and the value during the execution, but I will speak about it in the future.&lt;/p&gt;
&lt;p&gt;To reinforce the Marble Diagram concept let me show you another example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { delay, map } from &quot;rxjs/operators&quot;;

const source$ = new Observable&amp;lt;number&amp;gt;(observer =&amp;gt; {
  let count = 0;
  const id = setInterval(() =&amp;gt; {
    if (count++ &amp;lt; 3) {
      observer.next(count);
    } else {
      clearInterval(id);
      observer.complete();
    }
  }, 1000);
});

source$
  .pipe(
    map(value =&amp;gt; value * 2),
    delay(1500)
  )
  .subscribe({
    next: console.log,
  });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In this example you can see how the observable in the first operator doubles the value and then it waits 1.5 seconds before emitting the result.
To represent this case the marble diagram has 3 timelines, one with the source, one with the map operator and one with the delay operator. Every timeline indicates the value during the execution of its operator so you can see the behaviour of this implementation.&lt;/p&gt;
&lt;p&gt;It&apos;s all from the marble diagram.&lt;/p&gt;
&lt;p&gt;See you soon guys!&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Operators</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-operators/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-operators/</guid><description>Hi Guys and welcome back, today I introduce the concepts of Operators. Operators are functions. Isn&apos;t...</description><pubDate>Fri, 10 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Guys and welcome back, today I introduce the concepts of &lt;strong&gt;Operators&lt;/strong&gt;.
Operators are functions. Isn&apos;t it easy? Operators are functions of two types in RxJS: &lt;em&gt;Creation&lt;/em&gt; or &lt;em&gt;Pipeable&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Creation&lt;/h2&gt;
&lt;p&gt;Creation operators are simple functions and their scope is to create new observables.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { of } from &quot;rxjs&quot;;

of(1, 2, 3, 4).subscribe(x =&amp;gt; console.log(&quot;[of] result&quot;, x));
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[of] result 1
[of] result 2
[of] result 3
[of] result 4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The most commons creation operators are: ajax, empty, from, fromEvent, interval, of, throwError, timer, combineLatest, concat, forkJoin, merge and zip.&lt;/p&gt;
&lt;p&gt;In the next article I&apos;ll deepen these types of operators, today I just make an overview of the operator&apos;s types.&lt;/p&gt;
&lt;h2&gt;Pipeable&lt;/h2&gt;
&lt;p&gt;Pipeable operators are functions that take an Observable as input and return another observable. These functions are pure, so the input observable does not change but the function returns a new one. The main scopes of these operators are: transform, filter, and work with the input observable.
An example of pipeable operators:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Observable } from &quot;rxjs&quot;;
import { map, tap } from &quot;rxjs/operators&quot;;

new Observable&amp;lt;number&amp;gt;(observer =&amp;gt; {
  observer.next(1);
  observer.next(2);
  observer.next(3);
  observer.next(4);

  observer.complete();
})
  .pipe(
    map(val =&amp;gt; val * 2),
    tap(res =&amp;gt; {
      console.log(&quot;[pipeable tap]&quot;, res);
    })
  )
  .subscribe();
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[pipeable tap] 2
[pipeable tap] 4
[pipeable tap] 6
[pipeable tap] 8
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The pipeable operators are divided by scopes and the scopes are: Transformation, Filtering, Join, Multicasting, Error Handling, Utility, Conditional and Boolean and Mathematical and Aggregate.&lt;/p&gt;
&lt;p&gt;As you can understand you can combine Creation operators with Pipeable operators to manage your business logic like here&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { timer } from &quot;rxjs&quot;;
import { take } from &quot;rxjs/operators&quot;;

timer(0, 1000)
  .pipe(take(10))
  .subscribe(x =&amp;gt; console.log(&quot;[timer] result&quot;, x));
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[timer] result 0
[timer] result 1
[timer] result 2
[timer] result 3
[timer] result 4
[timer] result 5
[timer] result 6
[timer] result 7
[timer] result 8
[timer] result 9
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this last article, I have introduced all the pillars to the base of the RxJS library and the Reactive Programming. In the next article, we&apos;ll start to explore the operator&apos;s world.&lt;/p&gt;
&lt;p&gt;That&apos;s all guys,
See you soon!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https://github.com/Puppo/rxjs-getting-started/tree/03-operators&quot;&gt;in the GitHub repository&lt;/a&gt; you can find the code of this article.&lt;/em&gt;&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Observer and Subscription</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-observer-and-subscription/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-observer-and-subscription/</guid><description>Welcome back guys, today the topics of the article are Observers and Subscriptions. ...</description><pubDate>Wed, 08 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome back guys,
today the topics of the article are &lt;strong&gt;Observers&lt;/strong&gt; and &lt;strong&gt;Subscriptions&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Observer&lt;/h2&gt;
&lt;p&gt;An observer is a consumer of values. An observer is something that is interested to the emitted values by the observable. In RxJS an Observer is simply a set of callbacks (next, error, complete).
Here&apos;s a simple example of an observer&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Observer } from &quot;rxjs&quot;;

const observer: Observer&amp;lt;string&amp;gt; = {
  next: (value: string) =&amp;gt;
    console.log(`[observer] next`, value),
  error: (error: Error) =&amp;gt;
    console.error(`[observer] error`, error),
  complete: () =&amp;gt;
    console.log(`[observer] complete!`),
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see an observer has three callbacks, one for each type of notification that an Observable may emit. Every callback can react in the base of the observable event notification.
An observer could have not all the three callbacks defined because maybe it doesn&apos;t want to react to all the notifications. In these cases, you can create an observer with the only callbacks you need.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import {
  NextObserver,
  ErrorObserver,
  CompletionObserver,
} from &quot;rxjs&quot;;

const nextObserver: NextObserver&amp;lt;string&amp;gt; = {
  next: (value: string) =&amp;gt;
    console.log(`[nextObserver] next`, value),
};

const errorObserver: ErrorObserver&amp;lt;string&amp;gt; = {
  error: (error: Error) =&amp;gt;
    console.error(`[errorObserver] error`, error),
};

const completeObserver: CompletionObserver&amp;lt;string&amp;gt; = {
  complete: () =&amp;gt;
    console.log(`[completeObserver] complete!`),
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&apos;s possible to define a NextObserver without the next property but indicating only the body of the next method, in this case, the observer by default is of the type NextObserver.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const defaultNextObserver: (value: string) =&amp;gt; void = (value: string) =&amp;gt;
    console.log(`${new Date().toISOString()} - [defaultNextObserver] next`, value)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Subscription&lt;/h2&gt;
&lt;p&gt;A Subscription is an actor that decides when an Observable must be listened and when we can stop listening to it.
Until an observable is not subscribed in your code nothing happens, but as soon as you create a subscription, the magic starts.
A Subscription in RxJS is an object created using the method &quot;subscribe&quot; and it has one main method: &quot;unsubscribe&quot;; this method allows you to stop listening the observable event.
&lt;em&gt;In your code is &lt;strong&gt;important&lt;/strong&gt; to call the &quot;unsubscribe&quot; when you no longer need the subscription, this prevent problems as the memory leaks.&lt;/em&gt;
An example of a Subscription&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Subscription } from &quot;rxjs&quot;;

const observer = (value: string) =&amp;gt; console.log(`[unsubscribe method] next`, value)

const subscription: Subscription = observable.subscribe(observer);
subscription.unsubscribe();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another pretty feature in RxJS Subscription is the &quot;add&quot; method; this method allows you to collect more subscriptions inside of one Subscription instance and after that, you can unsubscribe all the subscriptions at once time.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Subscription } from &quot;rxjs&quot;;

const subscription: Subscription = observable.subscribe((value: string) =&amp;gt;
  console.log(
    `[unsubscribe 1 method] next`,
    value
  )
);
subscription.add(
  observable.subscribe((value: string) =&amp;gt;
    console.log(
      `[unsubscribe 2 method] next`,
      value
    )
  )
);

subscription.unsubscribe();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In some cases when you call the unsubscribe method you need to run some special code in your observable: RxJS let us do this using a special syntax inside of the observable declaration. When you create the observable you can return a function that the library invokes in the future during the unsubscription. Below a simple example to understand better the problem and the solution:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import {
  Observable,
  Subscriber,
  Subscription,
} from &quot;rxjs&quot;;

const observableWithCallback = new Observable&amp;lt;string&amp;gt;(
  (subscriber: Subscriber&amp;lt;string&amp;gt;) =&amp;gt; {
    let count = 0;
    const id = setInterval(() =&amp;gt; {
      subscriber.next(`Count: ${++count}`);
    }, 300);

    return () =&amp;gt; {
      console.log(&quot;On UnSubscription&quot;);
      clearInterval(id);
    };
  }
);

const subscriptionObservableWithCallback: Subscription = observableWithCallback.subscribe({
  next: (value: string) =&amp;gt;
    console.log(`[observableWithCallback] Next: ${value}`),
});
setTimeout(() =&amp;gt; {
  subscriptionObservableWithCallback.unsubscribe();
}, 3000);

&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;[observableWithCallback] Next: Count: 1
[observableWithCallback] Next: Count: 2
[observableWithCallback] Next: Count: 3
[observableWithCallback] Next: Count: 4
[observableWithCallback] Next: Count: 5
[observableWithCallback] Next: Count: 6
[observableWithCallback] Next: Count: 7
[observableWithCallback] Next: Count: 8
[observableWithCallback] Next: Count: 9
On UnSubscription
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok, guys, that&apos;s all for today.
In the next article we&apos;ll see the last fundamental of RxJS: the &lt;em&gt;Operator&lt;/em&gt; and later, we can move to see the features of this Library.&lt;/p&gt;
&lt;p&gt;You can find the examples of this article &lt;a href=&quot;https://github.com/Puppo/rxjs-getting-started/tree/02-observer-and-subscription&quot;&gt;in the GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you soon guys!&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>RxJS - Observable</title><link>https://delpuppo.net/blog/rxjs-getting-started/rxjs-observable/</link><guid isPermaLink="true">https://delpuppo.net/blog/rxjs-getting-started/rxjs-observable/</guid><description>Hi Guys, Today I want to start a little series about Reactive Programming with RxJS. I start from the...</description><pubDate>Mon, 06 Sep 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Guys,
Today I want to start a little series about Reactive Programming with &lt;a href=&quot;https://rxjs.dev/&quot;&gt;RxJS&lt;/a&gt;.
I start from the basic core concepts behind of this Programming Paradigm to move after and show the potentialities of the RxJS library.&lt;/p&gt;
&lt;p&gt;The idea of this series was born some weeks ago during a refactor in an Angular application, because I noticed a lot of errors in the codebase about RxJS. The problem behind this code unfortunately is that the developers begin using the angular framework without the basics of the RxJS library and the Reactive Programming. So I decided to write some articles to show the basics behind the RxJS library and Reactive Programming in general.&lt;/p&gt;
&lt;p&gt;A little preamble before passing on the topic of this article: RxJS is a library for composing asynchronous and event-based programs by using observable sequences. So RxJS and Reactive Programming are not the solution for all your problems, but they are good solutions in contexts where asynchronous and events are the stars. I&apos;ve preferred to clarify that because sometimes programmers believe that but after having introduced the Reactive Programming, they come across with other problems because the library and the paradigm are very simple but at the same time it&apos;s easy to get hurt if you don&apos;t know how it works.&lt;/p&gt;
&lt;p&gt;The last info about the series: the code is written in Typescript, but you can use RxJS also in vanilla javascript if you prefer.&lt;/p&gt;
&lt;p&gt;Now let&apos;s start with the first argument, the star behind the Reactive Programming, the &lt;em&gt;Observable&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Observables (the one who is observed) are one of the key concepts behind Reactive Programming along with Observers and Subscribers (those who observes, controls).
Observables can be a stream or a collection of datas, but you could imagine an observable like a lazy Push collection of multiple values.
To understand better the concept let me show you an example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Observable, Subscriber } from &quot;rxjs&quot;;

const observable = new Observable&amp;lt;string&amp;gt;((subscriber: Subscriber&amp;lt;string&amp;gt;) =&amp;gt; {
  subscriber.next(&quot;Hello World&quot;);
  subscriber.error(new Error(&quot;Something went wrong!&quot;));
  subscriber.complete();
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see the Observable is a class that accept a subscriber (a callback function).
This subscriber has 3 main possible action:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;next&lt;/strong&gt;: The next method emits the value passing as parameter to all the subscriptions, so the system can react accordingly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;error&lt;/strong&gt;: The error method emits an error during the execution of the observable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;complete&lt;/strong&gt;: The complete method sets the observable closed. When this happens, all the future methods (next and error) emitted for the closed observable will be ignored.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To better understand here&apos;s another example, with its result in the console&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Observable, Observer, Subscriber } from &quot;rxjs&quot;;

const observer: Observer&amp;lt;string&amp;gt; = {
  next: (value: string) =&amp;gt; console.log(&quot;next&quot;, value),
  error: (error: Error) =&amp;gt; console.error(&quot;error&quot;, error),
  complete: () =&amp;gt; console.log(&quot;complete!&quot;),
};

const observable = new Observable&amp;lt;string&amp;gt;((subscriber: Subscriber&amp;lt;string&amp;gt;) =&amp;gt; {
  subscriber.next(&quot;Hello&quot;);
  subscriber.next(&quot;World&quot;);

  subscriber.complete();

  // this will never be logged

  subscriber.error(new Error(&quot;Something went wrong!&quot;));

  subscriber.next(&quot;Hello&quot;);
  subscriber.next(&quot;World&quot;);
});

observable.subscribe(observer);
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;next Hello
next World
complete!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;p.s. don&apos;t pay attention to the observer in this moment, to simplify it think that when the subscriber calls the next method, the next function in the observer will be called and the same goes for the error and complete methods&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You can notice how the subscriber calls the next method twice: first with &quot;Hello&quot; and after with &quot;World&quot; and the result is logged into the console. Next, the subscriber calls the complete method and it is registered in the console too. After that, the subscriber calls the error method and the next method twice, but in the console nothing happens. This behaviour is due to the fact that the observable is ended by the complete method so the observable no longer emits any events.
When we complete the observable, it&apos;s important to remember that all the next methods called (next, error or complete) are ignored.&lt;/p&gt;
&lt;p&gt;That&apos;s all for now.
You can find the example at this &lt;a href=&quot;https://github.com/Puppo/rxjs-getting-started/tree/01-observable&quot;&gt;in the GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See you soon guys!&lt;/p&gt;
</content:encoded><category>javascript</category><category>typescript</category><category>rxjs</category></item><item><title>Typescript - Tips &amp; Tricks - Rest Parameters &amp; Rest Arguments</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-rest-parameters-rest-arguments/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-rest-parameters-rest-arguments/</guid><description>Hi guy and welcome back :) Today I&apos;ll talk about the Rest Parameters and the Rest...</description><pubDate>Fri, 02 Apr 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi guy and welcome back :)
Today I&apos;ll talk about the Rest Parameters and the Rest Arguments.
Sometimes we need to write a simple code like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function multiply(a: number, b: number): number {
  return a * b;
}

const result1 = multiply(2, 2); // 4
const result2 = multiply(2, 3); // 3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but after a while the customer asks us to multiply for unbounded numbers, so we need to change our code.
In these cases, typescript helps us with a feature called Rest Parameters.
This feature permits us to identify this list of parameters as an array type so we can leave our consumer to call the method with the correct number of items he needs, and we can manipulate these parameters more easily.
Therefore the previous example can be transformed in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function multiply(a: number, ...args: number[]): number {
  return args.reduce((acc, curr) =&amp;gt; acc * curr, a);
}

const result1 = multiply(2, 2, 2); // 8
const result2 = multiply(2, 3, 2, 2); // 24
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, now the consumer can call the &quot;multiply&quot; method as he prefers and our code responds correctly in all cases.
In this example, we have called the &quot;multiply&quot; method with a fixed number of elements, 3 in the first case and 4 in the second one. But in some cases, we don&apos;t know the correct number of elements and maybe they are in an array.
To resolve these cases, typescript has another important feature tied to the Rest Parameters, the Rest Arguments.
This feature helps us to convert the array elements to a list of parameters.
Thus, we can call the &quot;multiply&quot; method in this way too.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const result1 = multiply(2, ...[2, 2]); // 8
const result2 = multiply(2, ...[3, 2, 2]); // 24
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think that these two features are really powerful, and can help you to manipulate large numbers of parameters and take your code simple and flexible.&lt;/p&gt;
&lt;p&gt;And now a special greeting.
This is the last post of this series &lt;a href=&quot;https://dev.to/puppo/series/11213&quot;&gt;Typescript - Tips &amp;amp; Tricks&lt;/a&gt;, I hope you enjoyed the series and it will help you in your daily work.&lt;/p&gt;
&lt;p&gt;Many Thanks to have read the series.
It&apos;s not a goodbye, I&apos;ll get back soon with other topics.&lt;/p&gt;
&lt;p&gt;Bye, Bye Guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Advanced Types</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-advanced-types/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-advanced-types/</guid><description>Hi Guys, Today I&apos;ll show you some advanced utilities exposed by the typescript language. Let&apos;s...</description><pubDate>Wed, 31 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi Guys,
Today I&apos;ll show you some advanced utilities exposed by the typescript language.
Let&apos;s start!&lt;/p&gt;
&lt;h2&gt;Utilities for Types&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype&quot;&gt;Partial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to add the optional modifier to all the properties of your type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type PartialPoint = Partial&amp;lt;{ x: number; y: number }&amp;gt;; // { x?: number | undefined; y?: number | undefined; }
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtype&quot;&gt;Required&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to remove the optional modifier to all the properties of your type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type RequiredPoint = Required&amp;lt;{ x?: number; y?: number }&amp;gt;; // { x: number; y: number; }
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype&quot;&gt;ReadOnly&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to add the read-only modifier to all the properties of your type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type ReadOnlyPoint = ReadOnly&amp;lt;{ x: number; y: number }&amp;gt;; // { readonly x: number; readonly y: number; }
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys&quot;&gt;Pick&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to get a subset of properties from another type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type PickPoint = Pick&amp;lt;{ x: number; y: number }, &quot;x&quot;&amp;gt;; // { x: number; }
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys&quot;&gt;Omit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to exclude some properties from another type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type OmitPoint = Omit&amp;lt;{ x: number; y: number }, &quot;x&quot;&amp;gt;; // { y: number; }
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeystype&quot;&gt;Record&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to map the properties of a type to another type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Point = {
  x: number;
  y: number;
};
type PointRecord = Record&amp;lt;keyof Point, number | null&amp;gt;; // { x: number | null; y: number | null; }
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#excludetype-excludedunion&quot;&gt;Exclude&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to remove some types from a &lt;a href=&quot;https://dev.to/puppo/typescript-tips-tricks-union-and-intersection-1a9l&quot;&gt;union type&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type ExcludeType = Exclude&amp;lt;&quot;x&quot; | &quot;y&quot;, &quot;x&quot;&amp;gt;; // &quot;y&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union&quot;&gt;Extract&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to get some types from a &lt;a href=&quot;https://dev.to/puppo/typescript-tips-tricks-union-and-intersection-1a9l&quot;&gt;union type&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type ExtractType = Extract&amp;lt;&quot;x&quot; | &quot;y&quot;, &quot;x&quot;&amp;gt;; // &quot;x&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#nonnullabletype&quot;&gt;NonNullable&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to remove the &lt;em&gt;undefined&lt;/em&gt; and &lt;em&gt;null&lt;/em&gt; types from a &lt;a href=&quot;https://dev.to/puppo/typescript-tips-tricks-union-and-intersection-1a9l&quot;&gt;union type&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type NonNullableType = NonNullable&amp;lt;string | number | undefined | null&amp;gt;; // string | number
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Utilities for Function and Class&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype&quot;&gt;Parameters&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to extract from a function its parameters.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function createPoint(x: number, y: number) {
  return { x, y };
}
type ParametersType = Parameters&amp;lt;typeof createPoint&amp;gt;; // [x: number, y: number]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#constructorparameterstype&quot;&gt;ConstructorParameters&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to extract from a class its constructor parameters.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Point {
  constructor(x: number, y: number) {}
}
type ConstructorParametersType = ConstructorParameters&amp;lt;typeof Point&amp;gt;; // [x: number, y: number]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype&quot;&gt;ReturnType&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to get the return type from a function.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function createPoint(x: number, y: number) {
  return { x, y };
}
type CreatePointReturnType = ReturnType&amp;lt;typeof createPoint&amp;gt;; // { x: number; y: number; }
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#instancetypetype&quot;&gt;InstanceType&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to construct a type consisting of the instance type of a construction function type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class Point {
  constructor(x: number, y: number) {}
}
type InstanceTypePoint = InstanceType&amp;lt;typeof Point&amp;gt;; // Point
type InstanceTypeString = InstanceType&amp;lt;string&amp;gt;; // Error: Type &apos;string&apos; does not satisfy the constraint &apos;new (...args: any) =&amp;gt; any&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#thisparametertypetype&quot;&gt;ThisParameterType&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to extract the &lt;a href=&quot;https://dev.to/puppo/typescript-tips-tricks-this-parameter-7n6&quot;&gt;this parameter&lt;/a&gt; from a function type, or unknown if the function type has no this parameter.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function toHex(this: Number) {
  return this.toString(16);
}
function numberToString(n: ThisParameterType&amp;lt;typeof toHex&amp;gt;) {
  return toHex.apply(n);
}
numberToString(12)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#omitthisparametertype&quot;&gt;OmitThisParameter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to remove the &lt;a href=&quot;https://dev.to/puppo/typescript-tips-tricks-this-parameter-7n6&quot;&gt;this parameter&lt;/a&gt; from a function type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function toHex(this: Number) {
  return this.toString(16);
}
const fiveToHex: OmitThisParameter&amp;lt;typeof toHex&amp;gt; = toHex.bind(5);
fiveToHex()
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Utilities to Manipulation String Types&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Uppercase&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows converting your types to uppercase format.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type StringUppercase = Uppercase&amp;lt;&quot;getX&quot; | &quot;getY&quot; | &quot;setX&quot; | &quot;setY&quot;&amp;gt;; // &quot;GETX&quot; | &quot;GETY&quot; | &quot;SETX&quot; | &quot;SETY&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Lowercase&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to convert your types to lowercase format.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type StringLowercase = Lowercase&amp;lt;&quot;getX&quot; | &quot;getY&quot; | &quot;setX&quot; | &quot;setY&quot;&amp;gt;; // &quot;getx&quot; | &quot;gety&quot; | &quot;setx&quot; | &quot;sety&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Capitalize&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to convert your types to capitalize format.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type StringCapitalize = Capitalize&amp;lt;&quot;getX&quot; | &quot;getY&quot; | &quot;setX&quot; | &quot;setY&quot;&amp;gt;; // &quot;GetX&quot; | &quot;GetY&quot; | &quot;SetX&quot; | &quot;SetY&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Uncapitalize&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This utility allows you to convert your types to uncapitalize format.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type StringUncapitalize = Uncapitalize&amp;lt;&quot;GetX&quot; | &quot;GetY&quot; | &quot;SetX&quot; | &quot;SetY&quot;&amp;gt;; // &quot;getX&quot; | &quot;getY&quot; | &quot;setX&quot; | &quot;setY&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I hope these utilities will help you in the future.
That&apos;s all for today.
See you soon Guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Mapped Types</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-mapped-types/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-mapped-types/</guid><description>In some cases, we need to manipulate some types to create new types. In these cases, we have to use...</description><pubDate>Mon, 29 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In some cases, we need to manipulate some types to create new types. In these cases, we have to use the Mapped Types.
Let&apos;s start explaining the structure of the mapped types.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type MappedTypeExample = {
    [Key in &quot;x&quot; | &quot;y&quot; | &quot;z&quot;]: number;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, a mapped type is a type composed of defined keys and their values, but the power of the mapped types goes out when we want to joke with a generic type.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Point = {
    readonly x: number;
    y: number;
    z?: number;
};

type MappedType&amp;lt;T&amp;gt; = {
    [K in keyof T]: T[K];
};

type mappedPoint = MappedType&amp;lt;Point&amp;gt;;
/**
 type mappedPoint = {
    readonly x: number;
    y: number;
    z?: number | undefined;
}
*/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this simple example, I show you how to replicate the same object using the mapped type.
Now let&apos;s add two simple bits to transform our type into new &quot;different&quot; types. The mapped type permits you to add(+) or remove(-) the read-only modifier from your type but also to add(+) or remove(-) the optional modifier.
I leave you two simple examples to show these cases.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type MappedPointPlusModifier&amp;lt;T&amp;gt; = {
    +readonly [K in keyof T]: T[K];
};

type mappedPointPlusModifier = MappedPointPlusModifier&amp;lt;Point&amp;gt;;
/**
type mappedPointPlusModifier = {
    readonly x: number;
    readonly y: number;
    readonly z?: number | undefined;
}
*/

type MappedPointMinusModifier&amp;lt;T&amp;gt; = {
    [K in keyof T]-?: T[K];
};
type mappedPointMinusModifier = MappedPointMinusModifier&amp;lt;Point&amp;gt;;
/**
type mappedPointMinusModifier = {
    readonly x: number;
    y: number;
    z: number;
}
*/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;N.B. The add(+) modifier isn&apos;t indicated in common cases because it is implied&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The mapped types are a powerful feature to manipulate our types and they are used by the typescript team to expose to us some advanced types, but this is a topic of a future post.
Before ending I leave you another example to show what you can do with the mapped type.
In this example, I transform the Point type to another Point type where the fields aren&apos;t exposed directly but they are wrapped by a &quot;get&quot; and &quot;set&quot; method.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Getters&amp;lt;T&amp;gt; = {
  [K in keyof T as `get${Capitalize&amp;lt;string &amp;amp; K&amp;gt;}`]: () =&amp;gt; T[K];
};
type Setters&amp;lt;T&amp;gt; = {
  [K in keyof T as `set${Capitalize&amp;lt;string &amp;amp; K&amp;gt;}`]: (value: T[K]) =&amp;gt; void;
};
type WithGetterAndSetter&amp;lt;T&amp;gt; = Getters&amp;lt;T&amp;gt; &amp;amp; Setters&amp;lt;T&amp;gt;;

type Point = {
  x: number;
  y: number;
};

type WithGetterAndSetterPoint = WithGetterAndSetter&amp;lt;Point&amp;gt;;
/**
type WithGetterAndSetterPoint = {
  getX(): number;
  setX(value: number): void;
  getY(): number;
  setY(value: number): void;
}
*/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&apos;s all for today!
See you soon guy!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - infer keyword</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-infer-keyword/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-infer-keyword/</guid><description>Today I talk about the infer keyword. Sometimes, we need to get the value type of an array or get the...</description><pubDate>Fri, 26 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today I talk about the infer keyword.
Sometimes, we need to get the value type of an array or get the return type of a function. To do this I need to introduce the infer keyword.
To explain this feature I show you an example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type UnboxingArray&amp;lt;T&amp;gt; = T extends Array&amp;lt;infer Member&amp;gt; ? Member : T;

type UnboxingArrayString = UnboxingArray&amp;lt;string[]&amp;gt;; // string
type UnboxingArrayNumber = UnboxingArray&amp;lt;number[]&amp;gt;; // number
type UnboxingString = UnboxingArray&amp;lt;string&amp;gt;; // string
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, in the UnboxingArray type, we can detect if the T type extends an array and if so we can infer the element type or else we return the T type.
As a demonstration, if you see the type of the UnboxingArrayString and the UnboxingArrayNumber you can note how the UnboxingArray infers the string and the number type. In contrast, in the UnboxingString, the UnboxingArray can&apos;t infer the type of the elements because the type doesn&apos;t extend an array so it returns the string type.
Now I show you the infer keyword applied to the function result.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type ReturnType&amp;lt;T&amp;gt; = T extends (...args: unknown[]) =&amp;gt; infer R ? R : never;
function getPerson() {
  return {
    name: &quot;name&quot;,
    surname: &quot;surnmae&quot;,
  };
}
type Person = ReturnType&amp;lt;typeof getPerson&amp;gt;;
/**
type Person = {
  name: string;
  surname: string;
}
*/
type StringResult = ReturnType&amp;lt;string&amp;gt;; // never
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, you can note that if the T type extends a function, the ReturnType infers the type of the function result otherwise it returns the never type.
To demonstrate it, you can see how the Person type is composed of a name and a surname fields on the contrary the StringResult is of the never type.&lt;/p&gt;
&lt;p&gt;Great news for us, the &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype&quot;&gt;ReturnType&lt;/a&gt; is already included inside of the Typescript types.&lt;/p&gt;
&lt;p&gt;It&apos;s all guys.
Bye bye&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Conditional Type</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-conditional-type/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-conditional-type/</guid><description>In some cases, we need to detect if an object/type has specific properties or characteristics. Let me...</description><pubDate>Wed, 24 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In some cases, we need to detect if an object/type has specific properties or characteristics.
Let me show you a simple case&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type TypeName&amp;lt;T&amp;gt; =
    T extends string ? &quot;string&quot; :
    T extends number ? &quot;number&quot; :
    T extends bigint ? &quot;bigint&quot; :
    T extends boolean ? &quot;boolean&quot; :
    T extends undefined ? &quot;undefined&quot; :
    T extends symbol ? &quot;symbol&quot; :
    T extends Function ? &quot;function&quot; :
    T extends null ? &quot;null&quot; :
    &quot;object&quot;;

const typeName = &amp;lt;T&amp;gt;(obj: T): TypeName&amp;lt;T&amp;gt; =&amp;gt; {
  if (obj === null) return &quot;null&quot; as TypeName&amp;lt;T&amp;gt;;
  return typeof obj as TypeName&amp;lt;T&amp;gt;;
};

const stringType = typeName(&apos;string&apos;); // &quot;string&quot;
const numberType = typeName(10); // &quot;number&quot;
const bigIntType = typeName(10n); // &quot;bigint&quot;
const booleanType = typeName(true); // &quot;boolean&quot;
const undefinedType = typeName(undefined); // &quot;undefined&quot;
const symbolType = typeName(Symbol()); // &quot;symbol&quot;
const functionType = typeName(() =&amp;gt; &apos;result&apos;); // &quot;function&quot;
const nullType = typeName(null); // &quot;null&quot;
const objectType = typeName({ name: &apos;name&apos;}); // &quot;object&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, we return the type of the parameter as a string, but I want to focus on the TypeName type. This type as you can see, returns the values based on some conditions. In this case, the conditions are based on the parameter&apos;s type, but my goal is to show you that you could check if a type respects some conditions or not and act accordingly.
This feature is called Conditional Types.
To show you the power of this feature here a funny example found in the net :)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type SnackBars = {
  name: &quot;Short Chocolate Bars&quot;;
  amount: 4;
  candy: true;
};

type Gumballs = {
  name: &quot;Gooey Gumballs&quot;;
  color: &quot;green&quot; | &quot;purples&quot;;
  candy: true;
};

type Apples = {
  name: &quot;Apples&quot;;
  candy: true;
};

type Cookies = {
  name: &quot;Cookies&quot;;
  candy: true;
  peanuts: true;
};

type SnickersBar = {
  name: &quot;Snickers Bar&quot;;
  candy: true;
  peanuts: true;
};

type Toothpaste = {
  name: &quot;Toothpaste&quot;;
  minty: true;
  trick: true;
};

type Pencil = {
  name: &quot;Pencil&quot;;
  trick: true;
};

type HalloweenTricksAndSweets =
  | SnackBars
  | Gumballs
  | Apples
  | SnickersBar
  | Cookies
  | Toothpaste
  | Pencil;

type AllCandies&amp;lt;T&amp;gt; = T extends { candy: true } ? T : never;
type AllTricks&amp;lt;T&amp;gt; = T extends { trick: true } ? T : never;
type AllCandiesWithoutPeanuts&amp;lt;T&amp;gt; = T extends { candy: true } ? (T extends { peanuts: true } ? never : T) : never;

type Candies = AllCandies&amp;lt;HalloweenTricksAndSweets&amp;gt;; // SnackBars | Gumballs | Apples | SnickersBar | Cookies
type Tricks = AllTricks&amp;lt;HalloweenTricksAndSweets&amp;gt;; // Toothpaste | Pencil
type CandiesWithoutPeanuts = AllCandiesWithoutPeanuts&amp;lt;HalloweenTricksAndSweets&amp;gt;; // SnackBars | Gumballs | Apples
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, you can see how the AllCandies type creates a new type (Candies) composed of all the HalloweenTricksAndSweets that contain the candy property with the true value. The AllTricks type creates a new type (Tricks) composed of all the HalloweenTricksAndSweets that contain the trick property with the true value. The last case AllCandiesWithoutPeanuts is interesting: we get all the candies that don&apos;t contain the peanuts property with the true value.
I think this funny example can express best the potential of the Conditional Type, and it can help you to understand better all the benefits it can lead to.&lt;/p&gt;
&lt;p&gt;It&apos;s all for today.
I hope this feature will help you in the future as it helped me in some cases.&lt;/p&gt;
&lt;p&gt;See you soon Guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Type Guard</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-type-guard/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-type-guard/</guid><description>There are some cases, where we need to detect the type of the object to get the correct...</description><pubDate>Mon, 22 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;There are some cases, where we need to detect the type of the object to get the correct implementation of our method.
Let me show you a case&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Square = {
  size: number;
};

type Rectangle = {
  with: number;
  height: number;
};

type Circle = {
  radius: number;
};

type Shape = Square | Rectangle | Circle;

const area = (shape: Shape) =&amp;gt; {
  if (&quot;size&quot; in shape) return shape.size * shape.size;
  if (&quot;with&quot; in shape) return shape.with * shape.height;
  if (&quot;radius&quot; in shape) return shape.radius * 2 * Math.PI;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, in the area method, we need to detect the type of the shape to return the correct result.
Here we detect the type of the shape in the if condition but typescript permits us to create a special function that identifies if a type is of a specific type or not.
These functions are created to have Type Guards that help the compiler, the intellisense, and us to understand the correct type of the object.
To show you this function in action, the previous example can be rewritten in this way.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Square = {
  size: number;
};

type Rectangle = {
  with: number;
  height: number;
};

type Circle = {
  radius: number;
};

type Shape = Square | Rectangle | Circle;

function isSquare(shape: Shape): shape is Square {
  return &quot;size&quot; in shape;
}

function isRectangle(shape: Shape): shape is Rectangle {
  return &quot;with&quot; in shape;
}

function isCircle(shape: Shape): shape is Circle {
  return &quot;radius&quot; in shape;
}

const area = (shape: Shape) =&amp;gt; {
  if (isSquare(shape)) return shape.size * shape.size;
  if (isRectangle(shape)) return shape.with * shape.height;
  if (isCircle(shape)) return shape.radius * 2 * Math.PI;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, the methods: isSquare, isRectangle, and isCircle get a shape as parameter and return a boolean value. If the result is true the shape parameter corresponds to the type indicated to the right of the is keyword, otherwise, it corresponds to another type.&lt;/p&gt;
&lt;p&gt;I hope this feature will help you in the future and improve the reading of your code.&lt;/p&gt;
&lt;p&gt;It&apos;s all Guy!
See you soon!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Assert Function</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-assert-function/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-assert-function/</guid><description>There are times that we need to create some assertions to be sure an object respects some rules. A...</description><pubDate>Fri, 19 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;There are times that we need to create some assertions to be sure an object respects some rules.
A common case is to check if an object is defined; to do this you can create a simple assertion function like this&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function assert(condition: unknown, message: string): asserts condition {
  if (!condition) throw new Error(message);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To leave you a simple case of use, I write this simple example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Person = {
  name: string;
  email?: string;
};

function loadPerson(): Person | null {
  return null;
}

let person = loadPerson();

function assert(condition: unknown, message: string): asserts condition {
  if (!condition) throw new Error(message);
}

assert(person, &quot;Person is not defined&quot;); // Error: Person is not defined
console.log(person.name);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, in this example, the assert function detects if the person is defined and if the person isn&apos;t defined the assert function throws an error with the message that you pass in the parameters.
To level up, and explain better the power of the assert function, here another example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Square = {
  kind: &quot;square&quot;;
  size: number;
};

function ensureSquare(obj: unknown): asserts obj is Square {
  if (
    typeof obj === &quot;object&quot; &amp;amp;&amp;amp;
    !!obj &amp;amp;&amp;amp;
    &quot;kind&quot; in obj &amp;amp;&amp;amp;
    (obj as Square).kind === &quot;square&quot;
  )
    return;

  throw new Error(&quot;Object isn&apos;t a Square type&quot;);
}

const square = { kind: &quot;square&quot;, size: 10 };
ensureSquare(square);
// const square: Square
console.log(&quot;shape&quot;, square.kind);
console.log(&quot;size&quot;, square.size);

const rectangle = { kind: &quot;rectangle&quot;, width: 10, height: 15 };
ensureSquare(rectangle); // throw new Error(&quot;Object isn&apos;t a Square type&quot;);
console.log(&quot;shape&quot;, rectangle.kind);
console.log(&quot;size&quot;, rectangle.size);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, you can see how the &quot;ensureSquare&quot; function creates an assertion to detect if the object passed as parameter is of type Square or not.
If you see the part of the example where I created the square field, you can note that the type of the square field is &lt;code&gt;{ kind: string; size: number; }&lt;/code&gt;. If you observe the type of the square field after the &quot;ensureSquare(square);&quot; you can see how typescript converts the type of the field from &lt;code&gt;{ kind: string; size: number; }&lt;/code&gt; to Square.
This conversion is done because if the code passes the &quot;ensureSquare&quot; function you are sure that the &quot;square&quot; field is of type Square. On the contrary, in the second part of the example, the &quot;rectangle&quot; field, on runtime, throws an error, and the code after the &quot;ensureSquare&quot; function will never be executed.
I think you have understood the power of the assertion functions, and I hope they will help you to prevent some future mistakes.&lt;/p&gt;
&lt;p&gt;It&apos;s all guys, Bye Bye!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Never type</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-never-type/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-never-type/</guid><description>Today I want to talk about the never type. As you can understand, this type identifies a piece of...</description><pubDate>Wed, 17 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today I want to talk about the &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/2/narrowing.html#the-never-type&quot;&gt;never type&lt;/a&gt;.
As you can understand, this type identifies a piece of code that will never be executed or represents a state that shouldn’t exist.
Here an example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const throwException: () =&amp;gt; never = () =&amp;gt; {
    throw new Error();
};
throwException()
console.log(&apos;never called&apos;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this simple example, you can see how the &quot;throwException&quot; method never permits the code execution of the console.log. In this case, the &quot;throwException&quot; method returns the &lt;em&gt;never&lt;/em&gt; type because the method doesn&apos;t return any value but throws an error.
To better understand the never type I show you another simple example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Square = {
    kind: &quot;square&quot;;
    size: number;
};

type Rectangle = {
    kind: &quot;rectangle&quot;;
    with: number;
    height: number;
};

type Circle = {
    kind: &quot;circle&quot;;
    radius: number;
};

type Shape = Square | Rectangle | Circle;

const area = (shape: Shape): number =&amp;gt; {
    if (shape.kind === &quot;square&quot;) return shape.size * shape.size;
    if (shape.kind === &quot;rectangle&quot;) return shape.with * shape.height;
    // if (shape.kind === &quot;circle&quot;) return shape.radius * 2 * Math.PI;

    const _exhaustiveCheck: never = shape; // Type &apos;Circle&apos; is not assignable to type &apos;never&apos;.
    return _exhaustiveCheck;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, you can see how the &quot;area&quot; method detects the kind of the shape and it calculates the relative area.
I leave the circle type comment voluntarily, so I can show you the power of the never type.
At the end of the area method, you can see how the code assigns the shape to the field &quot;_exhaustiveCheck&quot; of type &lt;em&gt;never&lt;/em&gt;. In this case, the typescript language detects that if you pass a circle shape at the area method, the line &quot;const _exhaustiveCheck: never = shape;&quot; will be executed, so it notifies you raising an error. The typescript language detects that the never type could be executed at runtime so it tries to prevent this problem.
To fix this problem the previous method can be reviewed in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Square = {
    kind: &quot;square&quot;;
    size: number;
};

type Rectangle = {
    kind: &quot;rectangle&quot;;
    with: number;
    height: number;
};

type Circle = {
    kind: &quot;circle&quot;;
    radius: number;
};

type Shape = Square | Rectangle | Circle;

const area = (shape: Shape): number =&amp;gt; {
    if (shape.kind === &quot;square&quot;) return shape.size * shape.size;
    if (shape.kind === &quot;rectangle&quot;) return shape.with * shape.height;
    if (shape.kind === &quot;circle&quot;) return shape.radius * 2 * Math.PI;

    const _exhaustiveCheck: never = shape;
    return _exhaustiveCheck;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now the code is compiled successfully and the never type is assigned correctly.&lt;/p&gt;
&lt;p&gt;From the never type it&apos;s all.
See you soon guys&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Non-null assertion operator</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-non-null-assertion-operator/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-non-null-assertion-operator/</guid><description>In some cases, you have a field that you initialize in a method, and if you follow the flow of the...</description><pubDate>Mon, 15 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In some cases, you have a field that you initialize in a method, and if you follow the flow of the code you are sure that this field is initialized but typescript doesn&apos;t understand it.
An example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Person = {
  name: string;
};

let person: Person;

function initialize() {
  person = { name: &quot;name&quot; };
}

initialize();
console.log(&quot;Hello&quot;, person.name); // Variable &apos;person&apos; is used before being assigned.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, you can see how the typescript compiler doesn&apos;t understand that the &quot;person&quot; field isn&apos;t null but it&apos;s initialized.
To resolve this problem, the typescript language exposes us the &lt;em&gt;&quot;Non-null assertion operation&quot;&lt;/em&gt;(!). This operator says to the compiler that the field isn&apos;t null or undefined but it&apos;s defined.
The previous example can be reviewed in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Person = {
  name: string;
};

let person: Person;

function initialize() {
  person = { name: &quot;name&quot; };
}

initialize();
console.log(&quot;Hello&quot;, person!.name);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, in this case, the code doesn&apos;t have errors and the compilation ends with success.&lt;/p&gt;
&lt;p&gt;That&apos;s all for today!
Bye-bye guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Tuple</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-tuple/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-tuple/</guid><description>Tuple types allow you to express an array with a fixed number of elements whose types are known, but...</description><pubDate>Fri, 12 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Tuple types allow you to express an array with a fixed number of elements whose types are known, but need not be the same.
This definition is picking from the typescript documentation.
The tuple type is a powerful type that helps you to identify the types of elements in an array, you can create special types where the elements of the array can have different types.
A simple example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Point = [number, number];

const point1: Point = [10, 10];
const point2: Point = [10, &quot;10&quot;]; // Type &apos;string&apos; is not assignable to type &apos;number&apos;
const point3: Point = [10, 10, 20]; // Type &apos;[number, number, number]&apos; is not assignable to type &apos;Point&apos;. Source has 3 element(s) but target allows only 2.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, you can see how the point type is composed by a fixed array of two elements of type number. You can see how typescript detects this constraint and it raises an error when you try to create a point with the second element of type string or you try to create a point with 3 elements.
To show you the power of this type, here&apos;s another example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type QueryStringItem = [string, number | string | boolean];
const queryStringItem1: QueryStringItem = [&quot;key1&quot;, 10];
const queryStringItem2: QueryStringItem = [&quot;key2&quot;, &quot;value2&quot;];
const queryStringItem3: QueryStringItem = [&quot;key3&quot;, false];
const queryStringItem4: QueryStringItem = [&quot;key3&quot;, { value: &quot;value&quot; }]; // Type &apos;{ value: string; }&apos; is not assignable to type &apos;string | number | boolean&apos;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, you can see how the second element of the Tuple can be a &lt;a href=&quot;https://dev.to/puppo/typescript-tips-tricks-union-and-intersection-1a9l&quot;&gt;union type&lt;/a&gt; of the types: number, string, or boolean; so typescript let you set the second element of the Tuple with one of these last three types. If you try to set the second element with a different type from number, string or boolean the typescript compiler raises an error.&lt;/p&gt;
&lt;p&gt;That&apos;s all from the Tuple type.
See you soon guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Readonly Array</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-readonly-array/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-readonly-array/</guid><description>function sortAndReverse(list: number[]): number[] { return list.sort().reverse(); } const list =...</description><pubDate>Wed, 10 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;pre&gt;&lt;code&gt;function sortAndReverse(list: number[]): number[] {
  return list.sort().reverse();
}

const list = [1, 4, 5, 2];
sortAndReverse(list);
console.log(list);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What&apos;s the result of the final console log?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;[ 1, 4, 5, 2 ]&lt;/li&gt;
&lt;li&gt;[ 5, 4, 2, 1 ]&lt;/li&gt;
&lt;li&gt;[ 2, 5, 4, 1 ]&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Unfortunately, the correct answer is the second one.
&lt;/p&gt;
&lt;p&gt;In this stupid example, you can see how some array methods can have some side effects. The sort and the reverse methods return a new array with the result but also they change the initial array.
Typescript can help us to prevent these side effects using read-only arrays.
The read-only arrays identify the methods that modify the initial array and raise an error when you call these methods.
But now, how can you use the read-only array? It&apos;s easy guys, you need to indicate the readonly modifier before the type of your array.
So, the previous example can change in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function sortAndReverse(list: readonly number[]): number[] {
  return list.slice().sort().reverse();
}

const list = [1, 4, 5, 2];
sortAndReverse(list);
console.log(list);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, the &lt;em&gt;sortAndReverse&lt;/em&gt; method returns as result &quot;[ 5, 4, 2, 1 ]&quot; like in the first example, but more important is that the final console log returns &quot;[ 1, 4, 5, 2 ]&quot;, the initial value of the &quot;list&quot; array.
If in this case, you try to remove the &quot;slice&quot; method, you can see how typescript indicates an error (Property &apos;sort&apos; does not exist on type &apos;readonly number[]&apos;), and it helps you to prevent strange side effects.&lt;/p&gt;
&lt;p&gt;It&apos;s all for today!
Bye Bye Guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - readonly modifier</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-readonly-modifier/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-readonly-modifier/</guid><description>How many times we expect an object property to have a value but it isn&apos;t? In these cases,...</description><pubDate>Mon, 08 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;How many times we expect an object property to have a value but it isn&apos;t?

In these cases, unfortunately, we spend a lot of time searching for who changes the value of this property.
Today I want to show you a special modifier that helps you to prevent this problem and preserve your time.
This modifier is the &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-func.html#readonly-and-const&quot;&gt;readonly&lt;/a&gt;.
The readonly modifier helps you to prevent someone can change your property, so, the object&apos;s property can set only in the object initialization.
A simple example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Point = {
  x: number;
  y: number;
};
const point: Point = {
  x: 10,
  y: 10,
};
point.x = 20;
point.y = 20;

type ReadOnlyPoint = {
  readonly x: number;
  readonly y: number;
};
const readOnlyPoint: ReadOnlyPoint = {
  x: 10,
  y: 10,
};
readOnlyPoint.x = 20; // Cannot assign to &apos;x&apos; because it is a read-only property
readOnlyPoint.y = 20; // Cannot assign to &apos;y&apos; because it is a read-only property
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example you can see how in the first case you can change the value of the properties &apos;x&apos; and &apos;y&apos;; on the contrary, in the second case, you can&apos;t change the properties because they are marked as readonly.
As you can see, the readonly modifier can prevent the change of the values of the properties and save your code from annoying bugs.
Typescript also exposes a special type to convert your types to full readonly types; this type is called &lt;em&gt;ReadOnly&lt;/em&gt;.
So we can review the previous example in this way&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Point = {
  x: number;
  y: number;
};
const point: Point = {
  x: 10,
  y: 10,
};
point.x = 10;
const readOnlyPoint: ReadOnly&amp;lt;Point&amp;gt; = {
  x: 10,
  y: 10,
};
readOnlyPoint.x = 10; // Cannot assign to &apos;x&apos; because it is a read-only property
readOnlyPoint.y = 20; // Cannot assign to &apos;y&apos; because it is a read-only property
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From the readonly modifier, it&apos;s all!
Goodbye guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Index Signature</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-index-signature/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-index-signature/</guid><description>Welcome back guys, today I&apos;ll speak about the &quot;Index Signature&quot;. In some cases, we need to create...</description><pubDate>Fri, 05 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome back guys, today I&apos;ll speak about the &lt;em&gt;&quot;Index Signature&quot;&lt;/em&gt;.
In some cases, we need to create some special types like dictionaries.
These special types have some keys that identifies the elements and the datas.
A simple example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export type User = {
    name: string,
    email: string;
    session: string
}

export type UserDictionary = {
    [username: string]: User
}

const userDictionary: UserDictionary = {
  &apos;myusername&apos;: { email: &quot;myemail@email.it&quot;, name: &quot;myname&quot;, session: &quot;session&quot; },
  &apos;myusername1&apos;: {
    email: &quot;myemail1@email.it&quot;,
    name: &quot;myname1&quot;,
    session: &quot;session&quot;,
  },
};

console.log(userDictionary.myusername); // { email: &apos;myemail@email.it&apos;, name: &apos;myname&apos;, session: &apos;session&apos; }
console.log(userDictionary[&quot;myusername&quot;]); // { email: &apos;myemail@email.it&apos;, name: &apos;myname&apos;, session: &apos;session&apos; }
console.log(userDictionary.myusername1); // { email: &apos;myemail1@email.it&apos;, name: &apos;myname1&apos;, session: &apos;session&apos; }
console.log(userDictionary[&quot;myusername1&quot;]); // { email: &apos;myemail1@email.it&apos;, name: &apos;myname1&apos;, session: &apos;session&apos; }
delete userDictionary.myusername;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, the &lt;em&gt;UserDictionary&lt;/em&gt; is a special type where the usernames are the keys of the objects and the user data are the values.
This type is powerful because it permits the consumer to access directly to the data if it knows the keys and it permits to store a unique value of a specific key.
With the index signature, we can create special types where the keys can be string or number.
An important thing that you must remember is that the keys of these objects can be iterated with the for-in loop or with the Object.keys method.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;console.log(Object.keys(userDictionary)); // [ &apos;myusername&apos;, &apos;myusername1&apos; ]
for (const key in userDictionary) {
  console.log(key);
}
/*
&apos;myusername&apos;
&apos;myusername1&apos;
*/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&apos;s all from the &lt;em&gt;Index Signature&lt;/em&gt; for today.
Bye-bye guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Optional modifier</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-optional-modifier/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-optional-modifier/</guid><description>Hi guys and welcome back, Today I&apos;ll talk about the optional modifier. Sometimes we have objects that...</description><pubDate>Wed, 03 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi guys and welcome back,
Today I&apos;ll talk about the optional modifier.
Sometimes we have objects that have some optional properties.
In these cases, we need to identify the optional and the required properties, so the consumers can know what is required and what not.
To do this in typescript we have a special modifier named &quot;optional&quot; and it is identified by a question mark (&lt;em&gt;?&lt;/em&gt;).
Let&apos;s see an example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export type Person = {
  name: string;
  surname: string;
  email: string;
  phone?: string;
};

const person1: Person = {
  name: &quot;name1&quot;,
  surname: &quot;surname1&quot;,
  email: &quot;email1@email1.it&quot;,
};

const person2: Person = {
  name: &quot;name2&quot;,
  surname: &quot;surname2&quot;,
  email: &quot;email2@email2.it&quot;,
  phone: &quot;123&quot;,
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example we can see the optional modifier in action, the &quot;phone&quot; property is marked as optional so in the &quot;person1&quot; object we can avoid setting the &quot;phone&quot; property.
This modifier, also, could be used in the functions&apos; parameters if we have one or more optional parameters.
A simple example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function printPerson(name: string, email: string, phone?: string): void {
  console.log(`Name: ${name}`);
  console.log(`Email: ${email}`);
  if (phone) console.log(`Phone: ${phone}`);
}

printPerson(&quot;name1&quot;, &quot;email1@email1.it&quot;);
/*
  Name: name1
  Email: email1@email1.it
*/
printPerson(&quot;name2&quot;, &quot;email2@email1.it&quot;, &quot;123&quot;);
/*
  Name: name2
  Email: email2@email1.it
  Phone: 123
*/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see how in the first example we can avoid setting the phone parameter because it&apos;s optional.&lt;/p&gt;
&lt;p&gt;From the optional modifier, it&apos;s all.
See you soon guy!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - any vs. unknown</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-any-vs-unknown/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-any-vs-unknown/</guid><description>Hi guys, today I&apos;ll talk about the difference between any and unknown. Any Any type is a particular...</description><pubDate>Mon, 01 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi guys, today I&apos;ll talk about the difference between &lt;em&gt;any&lt;/em&gt; and &lt;em&gt;unknown&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Any&lt;/strong&gt;
Any type is a particular type in typescript.
If you use this type, the compiler doesn&apos;t check your code, and the power is in your hands, but from great powers comes great responsibilities. In this case, the compiler doesn&apos;t check your code, but maybe your code could have bugs; these bugs will most likely be found by a user during his operations.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unknown&lt;/strong&gt;
Unknown type is another particular type in typescript, it&apos;s similar to &lt;em&gt;Any&lt;/em&gt; type but it helps us to prevent bugs at build time.
The unknown type helps us to force the check of its type before using it.&lt;/p&gt;
&lt;p&gt;Now let&apos;s turn to some examples.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Any Type&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let myAny: any = true
myAny.trim().reverse().split(&apos;,&apos;);
let myAnyNumeric: number = myAny;
const sum = myAnyNumeric + 3;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, we can see a problem right away; in the second line, we try to call the trim method on a boolean type. This code at runtime throws an exception, but we need to run this code to detect this bug.
In the third line instead, I set a boolean type to a numeric type, and in the next line, I add three to this value.
Ok, I think you have understood the possible problems you could have if you overuse any type.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Unkown Type&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let myUnknown: unknown = true;
myUnknown.trim(); // Property &apos;trim&apos; does not exist on type &apos;unknown&apos;.ts(2339)
let myAnyNumeric: number = myUnknown; // Type &apos;unknown&apos; is not assignable to type &apos;number&apos;.ts(2322)
if (typeof myUnknown === &apos;string&apos;) myUnknown.trim();
if (typeof myUnknown === &quot;number&quot;) {
  let myAnyNumeric: number = myUnknown;
  const sum = myAnyNumeric + 3;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, we can see the power of using unknown type instead of any type.
This type doesn&apos;t stop the compiler check but it helps us to check our type to prevent bugs at runtime.
Typescript understands what you want to do, and it indicates you the correct way to prevent bugs.&lt;/p&gt;
&lt;p&gt;After this post, I think that from now on you will prefer to use &lt;em&gt;unknown&lt;/em&gt; instead of &lt;em&gt;any&lt;/em&gt; and I know the reason ;)&lt;/p&gt;
&lt;p&gt;That&apos;s all!
Bye-bye guy!!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - this parameter</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-this-parameter/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-this-parameter/</guid><description>Hello everybody and welcome back, today I&apos;ll talk about this parameter. Sometimes we need to create...</description><pubDate>Fri, 26 Feb 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hello everybody and welcome back, today I&apos;ll talk about &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/functions.html#this-parameters&quot;&gt;this parameter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Sometimes we need to create functions that have to know the context to run correctly.
A simple example, the mathematical power must know the base and the exponent number to run correctly.
So we could create a simple method like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function pow(exponent: number) {
  return Math.pow(this.number, exponent);
}

const basePow = {
  base: 2,
  pow,
};

console.log(basePow.pow(2));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we build and run this code, the console log&apos;s result will be &quot;NaN&quot;, because in the pow method the value of the field &quot;this.number&quot; is undefined.
&lt;em&gt;N.B. if you build this code with the strict mode on true, the compiler detects the problem at build time and so the build fails&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;But now I explain the solution.
In this case, the problem is the &quot;number&quot; field that doesn&apos;t exist in this context.
Typescript helps us to prevent this error, it allows us to indicate the &quot;this&quot; type as a parameter.
To do this, we need to declare the &quot;this&quot; context as the first parameter of the function, so typescript detects the &quot;this&quot; type and it helps us to prevent errors and bugs.
So the code in the previous example should be rewritten like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function pow(this: { base: number }, exponent: number) {
  return Math.pow(this.base, exponent);
}

const basePow = {
  base: 2,
  pow,
};

console.log(basePow.pow(2));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, the result at runtime is &quot;4&quot; as expected.
If by chance we write the &quot;basePow&quot; object like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const basePow = {
  value: 2,
  pow,
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;when we try to call the method &quot;basePow.pow(2)&quot;, the typescript language detects the error, and in this case, when we try to build the code the build fails.&lt;/p&gt;
&lt;p&gt;That&apos;s all!
See you soon guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Overloaded Functions</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-overloaded-functions/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-overloaded-functions/</guid><description>Welcome back, guys! The topic of today is Overloaded Functions. All self-respecting programming...</description><pubDate>Wed, 24 Feb 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome back, guys!
The topic of today is &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/declaration-files/by-example.html#overloaded-functions&quot;&gt;Overloaded Functions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All self-respecting programming languages ​​have overloaded functions, so typescript has this feature too.
To use this feature in typescript, we have to declare all the signatures of this function, and at the end, we have to write a single function that includes all these signatures. The last function is the only one with the implementation. The peculiarity of this function is that it must include all the possible implementations of the previous signatures.
Here&apos;s a simple example that is more exhaustive than all these words.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function reverse(value: string): string;
function reverse(value: string[]): string[];
function reverse(value: string | string[]): string | string[] {
  if (typeof value === &quot;string&quot;) return value.split(&quot;&quot;).reverse().join(&quot;&quot;);

  return value.slice().reverse();
}

console.log(reverse(&quot;Tips&quot;)); // &apos;spiT&apos;
console.log(reverse([&quot;T&quot;, &quot;i&quot;, &quot;p&quot;, &quot;s&quot;])); // [ &apos;s&apos;, &apos;p&apos;, &apos;i&apos;, &apos;T&apos; ]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As we can see, there are 2 signatures of the &quot;reverse&quot; function, one gets a string and returns a string as result, the second one gets a string array and returns a string array as result. The third function is the real implementation of this function. As we can see the parameter type is a literal-type that includes a string or a string array (the combination of the type in the signatures&apos; parameters), we can make the same considerations for the result&apos;s type.
In the function implementations, we detect the parameter&apos;s type at runtime and manipulate the parameter to return the correct type according to the function we are overloading.&lt;/p&gt;
&lt;p&gt;An important thing to remember is that the implementation function is not exposed.&lt;/p&gt;
&lt;p&gt;That&apos;s all for today!
See you soon guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Union and Intersection</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-union-and-intersection/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-union-and-intersection/</guid><description>Hi and welcome back! Today I talk about Union and Intersection. In some cases, we have to combine...</description><pubDate>Mon, 22 Feb 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi and welcome back!
Today I talk about &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html&quot;&gt;Union and Intersection&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In some cases, we have to combine different types to create new types, or sometimes we have parameters that could be of different types.
Typescript helps us with two powerful features: &lt;em&gt;Union&lt;/em&gt;(|) and &lt;em&gt;Intersection&lt;/em&gt;(&amp;amp;).&lt;/p&gt;
&lt;h2&gt;Union&lt;/h2&gt;
&lt;p&gt;A union type describes a value that can be one of several types.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Padding = number | string
let paddingNumber: Padding = 1
let paddingString: Padding = &apos;----&apos;;
let paddingError: Padding = true // Type &apos;boolean&apos; is not assignable to type &apos;Padding&apos;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, the padding can be a number or a string, and the compiler detects if you set different types; this feature can be used also with custom types.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Fish = {
  name(): string;
  swim(): true;
};
type Cat = {
  name(): string;
  meows(): true;
};
type Pet = Fish | Cat; // { name(): string; }
declare function createPet(): Pet;
let pet = createPet();
pet.name()
pet.swim() // Property &apos;swim&apos; does not exist on type &apos;Pet&apos;
pet.meows(); // Property &apos;meows&apos; does not exist on type &apos;Pet&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example we can see how the union type creates the Pet type; the Pet type is composed by a single method &quot;name&quot;. This method is the only one present in the two initial types: Fish and Cat.&lt;/p&gt;
&lt;h2&gt;Intersection&lt;/h2&gt;
&lt;p&gt;An intersection type combines multiple types into one.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Point2D = {
  x: number;
  y: number;
};
type Point3D = Point2D &amp;amp; {
  z: number;
};
let point2d: Point2D = { x: 0, y: 0 };
let point3d: Point3D = { x: 0, y: 0, z: 0 };
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can see that the Point3D type is the union of the Type Point2D and the type { z: number; }.&lt;/p&gt;
&lt;p&gt;That&apos;s all for today!
See you soon guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - keyof</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-keyof/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-keyof/</guid><description>Welcome back! Today I&apos;ll talk about the keyof operator. This operator helps us to extract the...</description><pubDate>Fri, 19 Feb 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome back!
Today I&apos;ll talk about the &lt;strong&gt;keyof&lt;/strong&gt; operator.&lt;/p&gt;
&lt;p&gt;This operator helps us to extract the object&apos;s properties such as &lt;a href=&quot;https://dev.to/puppo/typescript-tips-tricks-literal-types-10md&quot;&gt;Literal-types&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Person = {
  firstName: string;
  surName: string;
  age: number;
  location: string;
};

type PersonKeys = keyof Person; // &quot;firstName&quot; | &quot;surName&quot; | &quot;age&quot; | &quot;location&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This operator can help us to create new methods that should depend of other types; e.g.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function get&amp;lt;T, K extends keyof T&amp;gt;(obj: T, prop: K): T[K] {
  return obj[prop];
}

function set&amp;lt;T, K extends keyof T&amp;gt;(obj: T, prop: K, value: T[K]): void {
  obj[prop] = value;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but also to create new types from other types e.g&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type ReadOnly&amp;lt;T&amp;gt; = {
  readonly [K in keyof T]: T[K];
};

type ReadOnlyPerson = ReadOnly&amp;lt;Person&amp;gt;
/*
type ReadOnlyPerson = {
    readonly firstName: string;
    readonly surName: string;
    readonly age: number;
    readonly location: string;
}
*/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How we can see this operator is more powerful and it can help us to create new strict type or new strict methods.&lt;/p&gt;
&lt;p&gt;That&apos;s all for today.
See you soon guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - Literal Types</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-literal-types/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-literal-types/</guid><description>Welcome back! Today I show you the Literal Types. This feature permits you to create a set of...</description><pubDate>Wed, 17 Feb 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome back!
Today I show you the &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/literal-types.html&quot;&gt;Literal Types&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This feature permits you to create a set of relationship values.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Direction = &quot;North&quot; | &quot;South&quot; | &quot;East&quot; | &quot;West&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Literal types in this case create also a Type Guard of your field, so the compiler can detect your errors or your typos.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let directionError: Direction = &quot;east&quot; // Type &apos;&quot;east&quot;&apos; is not assignable to type &apos;Direction&apos;
let direction: Direction = &quot;East&quot; // OK
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can create Literal Types from different types such as booleans, numbers, and strings, and you can combine together different types too.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Valid = false | 0 | true | 1;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&apos;s all for today
See you soon guys!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript - Tips &amp; Tricks - typeof</title><link>https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-typeof/</link><guid isPermaLink="true">https://delpuppo.net/blog/ts-tips-and-tricks/typescript-tips-tricks-typeof/</guid><description>Today I want to start a series of tips and tricks about Typescript. I will try to publish two/three...</description><pubDate>Mon, 15 Feb 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today I want to start a series of tips and tricks about Typescript.
I will try to publish two/three tips &amp;amp; tricks a week.
Before start, I want to explain why I start this series.
I start this series because every day I see too many &lt;em&gt;any&lt;/em&gt; types in the typescript files and so I want to help the developers to learn better the typescript language.&lt;/p&gt;
&lt;h2&gt;typeof&lt;/h2&gt;
&lt;p&gt;Today I start with the &lt;strong&gt;typeof&lt;/strong&gt; operator.
Typeof is an operator used to detect the type of our variables.
A little preamble, typeof is also a javascript operator, but with typescript, it has superpowers.&lt;/p&gt;
&lt;p&gt;Typeof in javascript has these behaviors:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const valueString = &quot;string&quot;;
const valueNumber = 1;
const valueBoolean = true;
const valueBigInt = 1n;
const valueFunction = () =&amp;gt; true;
const valueUndefined = undefined;
const valueNull = null;
const object = {
  prop1: &quot;value1&quot;,
  prop2: &quot;value2&quot;,
};

console.log(typeof valueString); // string
console.log(typeof valueNumber); // number
console.log(typeof valueBoolean); // boolean
console.log(typeof valueBigInt); // bigint
console.log(typeof valueFunction); // function
console.log(typeof valueUndefined); // undefined
console.log(typeof valueNull); // object
console.log(typeof object); // object
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How we can see some things are strange: e.g. when we get the typeof of a null variable javascript returns an object type.&lt;/p&gt;
&lt;p&gt;But here we see the same example in typescript:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type valueStringType = typeof valueString; // &quot;string&quot;
type valueNumberType = typeof valueNumber; // 1
type valueBooleanType = typeof valueBoolean; // true
type valueBigIntType = typeof valueBigInt; // 1n
type valueFunctionType = typeof valueFunction; // () =&amp;gt; boolean
type valueUndefinedType = typeof valueUndefined; // undefined
type valueNullType = typeof valueNull; // null
type objectType = typeof object; // { prop1: string; prop2: string; }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first impact is friendlier for us developers because the typeof operator converts the type exactly as expected. The best advantages can be seen in the types: function, null, object.&lt;/p&gt;
&lt;p&gt;But now an advanced example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const item = {
  id: &apos;0000&apos;,
  name: &apos;Item&apos;,
  unit: {
    id: &apos;1&apos;,
    code: &apos;PZ&apos;
  },
  variants: [{
    id: &apos;1&apos;,
    code: &apos;001&apos;,
    color: &apos;FFFFFF&apos;
  }]
};

type Item = typeof item;
type Unit = typeof item[&quot;unit&quot;];
type Variant = typeof item.variants[number];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, we can see how we can extract simple types from a complex object.&lt;/p&gt;
&lt;p&gt;I leave you the &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/2/typeof-types.html&quot;&gt;in this reference&lt;/a&gt; of the official documentation of this operator.&lt;/p&gt;
&lt;p&gt;For today is all.
See you soon!&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Typescript read-only object to an Enum type</title><link>https://delpuppo.net/blog/typescript-read-only-object-to-an-enum-type/</link><guid isPermaLink="true">https://delpuppo.net/blog/typescript-read-only-object-to-an-enum-type/</guid><description>Sometimes I need to convert a read-only object to an enum type; so I created a simple function utilit...</description><pubDate>Sat, 06 Feb 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Sometimes I need to convert a read-only object to an enum type; so I created a simple function utility that helps me to convert this object to an &quot;enum&quot; type.
This is the code to build the type.

Some examples of use.
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/Puppo/27f40b59bd3f497e3d1108b07a47678e/revisions&quot;&gt;Gits URL&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>typescript</category><category>webdev</category></item><item><title>Why TDD is not only code that tests your code</title><link>https://delpuppo.net/blog/why-tdd-is-not-only-code-that-tests-your-code/</link><guid isPermaLink="true">https://delpuppo.net/blog/why-tdd-is-not-only-code-that-tests-your-code/</guid><description>In this strange year, at the end of the summer, I decided to change my work experience. I had some ne...</description><pubDate>Wed, 30 Dec 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In this strange year, at the end of the summer, I decided to change my work experience. I had some new ambitions and a willingness to learn new things and improve others. One of the things I wanted to improve is unit testing, an argument that I couldn&apos;t practice in my past jobs, so I started to search for a new experience.&lt;/p&gt;
&lt;p&gt;After some job interviews, I made my decision, and in mid-November, I started my new experience.
In the first period, my time was divided in half between work and study.
The study was divide into two sections: corporate culture and technical culture.
Today I want to write some thoughts about a single point presents in the technical culture: Test-Driven Development (TDD).&lt;/p&gt;
&lt;h2&gt;What is TDD?&lt;/h2&gt;
&lt;p&gt;Test-driven development is a software development process relying on software requirements being converted to test cases before the software is fully developed, and tracking all software development by repeatedly testing the software against all test cases.
&lt;em&gt;For more developer is only a process known as &quot;write tests before your code&quot; (also for me until recently)&lt;/em&gt;
The method bases its power on a simple repeatable flow &quot;Red Green Refactor&quot;. In the red step, the developer must write the test for the next development feature; obviously, this test the first time fails because the code isn&apos;t present. In the green step, the developer must change the test spy from red to green with the minimum code possible. In the Refactor step, the developer can improve, review and organize the code if it&apos;s necessary.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;My study about TDD&lt;/h2&gt;
&lt;p&gt;Before starting my new work experience I had read some articles about this topic and a famous book known as the guide of the method &lt;a href=&quot;https://www.amazon.it/Test-Driven-Development-Example-Kent-Beck/dp/0321146530&quot;&gt;Test Driven Development. By Example&lt;/a&gt;, the author is &lt;a href=&quot;https://www.kentbeck.com/&quot;&gt;Kent Beck&lt;/a&gt;, I think introductions are unnecessary.
The book is very interesting and illustrates how to implement the method in the best way. It explains the bases of the method, it illustrates how to implement the method and it shows some best practices to improve the implementation during our work.
After this reading, I had to try to implement this method in my daily work but with greater difficulty, I didn&apos;t understand why but for me TDD started to be a difficult methodology to implement in my daily work. The time spent implementing the method reduced my productivity drastically and the time to release the new feature increased, so I decided to put it aside (I&apos;m talking about the period before changing my job).&lt;/p&gt;
&lt;h2&gt;TDD after changing my job&lt;/h2&gt;
&lt;p&gt;During my onBoarding, as I said before, I spent some time studying and practicing TDD. In this period I approached the method from a different point of view: &lt;a href=&quot;https://agilemanifesto.org/&quot;&gt;Agile&lt;/a&gt;.
&lt;code&gt;Agile is a practice that I studied much during my school period but I couldn&apos;t implement it in my previous jobs.&lt;/code&gt;
So I started to change my mind about TDD, from &quot;write tests before typing code&quot; to &quot;write the business requirement before typing the implementation&quot;. This new approach helps me to move my development from the output to the outcome and improves my velocity to implement the TDD method. Before this approach my mind spent too much time to discover all the possible failure of the code before start implement the feature, now my mind spends the right time to write the outcome of the code and after that, I type the code to change the test spy from red to green and then I refactor the code to review or organize it. Only after that, my mind spends not too much time to add tests that represent the extreme cases and if necessary I refactor the code to pass these cases as well.
Writing my tests by basing them on the outcome instead of the output changed also my idea about the TDD method, it&apos;s a powerful tool to improve our velocity and the consistency of our code. It helps us to rest assured during refactoring, it helps us to be sure of the delivery code, and our outcomes respect the business requirements.
The flow &quot;Red Green Refactor&quot; followed by us during the development helps us to follow the correct way and leave our mind free to create new features, when we break something the test suite notify us and we can fix the error before this goes live.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;TDD is a powerful method for me and I think also for thousands of developers in the world. In my opinion, in an agile context, but not only, it&apos;s an extraordinary tool to improve the confidence of the code but also to create powerful outcome documentations. It helps developers to think about the outcome of their work before typing a single raw of code, it helps them to write their code without fear of breaking something else, and I think these pros are not limited to developers but these are pros also for the stakeholders, the sponsors and all the members of the project.
It&apos;s a powerful tool also to have continuous feedback from our code, it helps us to stay confident and review our code in serenity.
Also, it helps us to increase our team with new developers because if a development breaks the code outcome the test suite notifies us and we can fix it quickly.&lt;/p&gt;
</content:encoded><category>tdd</category><category>programming</category><category>testing</category></item></channel></rss>