<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matthew Foley</title>
    <description>The latest articles on DEV Community by Matthew Foley (@mtfoley).</description>
    <link>https://dev.to/mtfoley</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F391207%2F3ea20bd5-0891-4025-bf72-51490099a21b.jpg</url>
      <title>DEV Community: Matthew Foley</title>
      <link>https://dev.to/mtfoley</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mtfoley"/>
    <language>en</language>
    <item>
      <title>Collab Lab #54 Recap</title>
      <dc:creator>Matthew Foley</dc:creator>
      <pubDate>Fri, 24 Mar 2023 18:04:32 +0000</pubDate>
      <link>https://dev.to/the-collab-lab/collab-lab-54-recap-2pcb</link>
      <guid>https://dev.to/the-collab-lab/collab-lab-54-recap-2pcb</guid>
      <description>&lt;h3&gt;
  
  
  OVERVIEW:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Collab Lab&lt;/strong&gt; is a non profit organization that helps early career developers and, in particular, people in under-represented groups in tech, gain experience they need to break into tech. To achieve that, over the course of 8 weeks a team of 4 junior developers work collaboratively on a software project, under the guidance of volunteer mentors. The goal is for them to gain hands-on experience by working in a professional setting with code reviews, pair programming sessions, weekly meetings and retro sessions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.youtube.com%2Fvi%2FLrxj92WQxTA%2Fmaxresdefault.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.youtube.com%2Fvi%2FLrxj92WQxTA%2Fmaxresdefault.jpg" alt="thumbnail for youtube video of weekly sync"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project is a “smart” shopping list that learns your behavior over time and prioritizes the things that you are going to need and reminds you to buy them. The developers had to work both on the functionality of the application and the appearance of it. Check out the deployed app &lt;br&gt;
&lt;a href="https://tcl-54-smart-shopping-list.web.app/" rel="noopener noreferrer"&gt;here&lt;/a&gt; and the repository &lt;a href="https://github.com/the-collab-lab/tcl-54-smart-shopping-list" rel="noopener noreferrer"&gt;here&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Technologies and Tools&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML/CSS/JavaScript&lt;/li&gt;
&lt;li&gt;UI Library: &lt;a href="https://reactjs.org" rel="noopener noreferrer"&gt;React&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Hosting &amp;amp; Database: &lt;a href="https://firebase.google.com/" rel="noopener noreferrer"&gt;Firebase&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;UI Styling: &lt;a href="https://getbootstrap.com/" rel="noopener noreferrer"&gt;Bootstrap&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Team
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Collabies
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/dantonioa/" rel="noopener noreferrer"&gt;Alexandria D'Antonio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/ashelle-cancio/" rel="noopener noreferrer"&gt;Ashelle Cancio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/randall-bustamante-85144bb/" rel="noopener noreferrer"&gt;Randall Bustamante&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/sarahmjenkins/" rel="noopener noreferrer"&gt;Sarah Jenkins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Mentors
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/dj-taylor-3b91ba3a/" rel="noopener noreferrer"&gt;DJ Taylor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/matthew-foley-00329316/" rel="noopener noreferrer"&gt;Matthew Foley&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.linkedin.com/in/volha-hancharova/" rel="noopener noreferrer"&gt;Volha Hancharova&lt;/a&gt; - Lead Mentor&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Day in Life of a Collabie
&lt;/h2&gt;

&lt;p&gt;The team of developers (called Collabies) met with the team of Mentors each Saturday for eight weeks, for a one hour "Weekly Sync" call on Zoom. The first order of business during the call was for the Collabies to demonstrate the previous week's work with technical details, and then switching gears to either a &lt;strong&gt;Retrospective&lt;/strong&gt; or a "Learning Module". In Retrospectives, both Collabies and Mentors took time to both celebrate and reflect on their prior two weeks experiences, being sure to document next steps. Learning Modules included talks delivered by Mentors on topics like &lt;strong&gt;Pair Programming&lt;/strong&gt;, &lt;strong&gt;Source Control (Git)&lt;/strong&gt;, &lt;strong&gt;Communication for Developers&lt;/strong&gt;, and &lt;strong&gt;Accessibility&lt;/strong&gt;. Lastly during these calls, the Mentors would present the following week's work, &lt;strong&gt;managed as issues in GitHub&lt;/strong&gt;. The Collabies would select their GitHub issues for the week, and get started!&lt;/p&gt;

&lt;p&gt;Between Weekly Syncs, the Collabies &lt;strong&gt;self-organized for pair programming&lt;/strong&gt; sessions and technical research, and sometimes divided up work for async tasks. Collabies made a good habit of &lt;strong&gt;starting Draft PRs&lt;/strong&gt; early in their process, so that the Mentors and Peers could easily collaborate with them if they got stuck, or contribute suggestions along the way. Around the middle of the week, each pair of Collabies performed &lt;strong&gt;code review&lt;/strong&gt; on the other pair's PR, and following that, the Mentors made their own code reviews. Once all was approved, the Collabies would &lt;strong&gt;SHIP IT&lt;/strong&gt;, ready to present in the Weekly Sync!&lt;/p&gt;

&lt;p&gt;In the 7th and 8th weeks, the routine changed - rather than the Mentors managing the process, &lt;strong&gt;the Collabies took over.&lt;/strong&gt; At this point, the functional requirements were substantially completed, and the Collabies focused on the appearance of the application.  They were given a goal of the app having a professional appearance, and they managed the entire process for the final two weeks, driving the project to completion! They created their own &lt;strong&gt;acceptance criteria&lt;/strong&gt;, delegated their own work, did pair programming when necessary, and leaned on each other and the Mentors when they got stuck. They practiced some Product Management skills by &lt;strong&gt;managing feature priorities&lt;/strong&gt;, and they also gained some experience of working in a &lt;strong&gt;team with velocity&lt;/strong&gt;, keeping tabs on each other's work and avoiding merge conflicts.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Few Words from the Collabies
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;From Ashelle Cancio&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My experience with The Collab Lab was fantastic. The mentors were always helpful and genuinely cared about our success. They shared their own experiences as developers, which was inspiring, and I learned a lot when pair-programming with the other participants. Through the program, I got the hang of the Agile workflow and became familiar with using a Kanban board to manage our weekly issues. While I knew basic Git commands, we encountered some merge conflicts, which was actually helpful because this forced me to learn new commands. I also realized the importance of code reviews. Overall, I am more confident in my coding abilities and feel prepared to review other developers' code in future projects. I am grateful for the experience and the knowledge gained from the mentors and fellow collabies!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;From Randall Bustamante&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Working with the mentors and collabies on our shopping list app was the most rewarding experience I've had with coding thus far.  Bootcamp was stressful and overwhelming.  Despite it being in person, I didn't quite get the support I needed.  The Collab Lab set this mentorship up perfectly!  The mentors guided us perfectly. They didn't solve our problems, but they empowered us to find resources and succeed thanks to our own efforts.  I learned A TON of knowledge that solidified skills I felt shaky on.  I met amazing humans who gave their time to help others.  I will forever be grateful for this experience.  Thank you, DJ Taylor, Volha Hancharova and Matthew Foley.  To my fellow collabies, huge thanks to Alexandria D'Antonio, Ashelle Cancio, and Sarah Jenkins for your collaboration and leadership!  And a final shout out to Alex Morton for watching over us to make sure all was good and healthy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;From Alexandria D'Antonio&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Being a part of this cohort was a transformative experience. Imposter syndrome was a huge hurdle I faced starting my journey as a software engineer. However, being a part of The Collab Lab was the clicking piece for me that confirmed I belong on this path. The experiences I've gained prior as a bootcamp graduate have all been short-term projects. Working with this amazing team for the last eight weeks showed me the collaborative dynamic of being in this kind of role. I loved it. I learned and applied new technical communication skills in writing pull requests, code reviews, and giving and receiving feedback. While having a lot of fun working with Sarah, Randall, and Ashelle, I also learned a lot from the different perspectives of my fellow Collabies. Instrumental to our success was the consistent support and guidance of our mentors Volha, Matt, and DJ. Each week, we were using new technical and documenting methods thanks to the mentors' thoughtful comments and recommendations. As a Collabie, I was able to build confidence in myself week by week during this program and will forever be thankful for this opportunity!&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;To wrap things up, everyone enjoyed the experience and there were all sorts of valuable learnings. The developers worked diligently to deliver a high quality application. Any organization would be lucky to have any of these developers on their team!&lt;/p&gt;

&lt;p&gt;If you are an early-career developer, the application for the next cohort is ongoing and this is a huge opportunity. &lt;a href="https://the-collab-lab.codes/participate/" rel="noopener noreferrer"&gt;Apply&lt;/a&gt;!!!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Converting to Vite (Part 4)</title>
      <dc:creator>Matthew Foley</dc:creator>
      <pubDate>Mon, 14 Feb 2022 16:18:49 +0000</pubDate>
      <link>https://dev.to/opensauced/converting-to-vite-part-4-ikf</link>
      <guid>https://dev.to/opensauced/converting-to-vite-part-4-ikf</guid>
      <description>&lt;p&gt;In Part 4 of this series, I'll be talking about some of ways the scope of &lt;a href="https://github.com/open-sauced/open-sauced/pull/1322"&gt;PR #1322&lt;/a&gt; grew to include cloud-based IDEs! As alluded to in &lt;a href="https://dev.to/opensauced/converting-to-vite-part-1-4ff4"&gt;Part 1&lt;/a&gt;, our conversion from &lt;a href="https://webpack.js.org/"&gt;Webpack&lt;/a&gt; to &lt;a href="https://vitejs.dev"&gt;Vite&lt;/a&gt; all started because of a discussion about opportunities for dependency updates in our project. Between this and us greatly reducing our build script footprint, we saw in this endeavor an additional opportunity for reduced friction in getting setup for Cloud IDE support. To us, Cloud IDE support presents an arguably easier path for prospective contributors, because it allows them to skip the hard parts of preparing their local environment for development.  &lt;/p&gt;

&lt;p&gt;Based on some back-and-forth in our &lt;a href="https://discord.gg/U2peSNf23P"&gt;Discord&lt;/a&gt;, we decided to try out a handful of Cloud IDEs.  Ultimately, this PR (and some ground-clearing ones that preceded it) introduced support for &lt;a href="https://www.gitpod.io/"&gt;Gitpod&lt;/a&gt;, &lt;a href="https://replit.com/"&gt;Replit&lt;/a&gt;, &lt;a href="https://stackblitz.com/"&gt;Stackblitz&lt;/a&gt;, and &lt;a href="https://glitch.com"&gt;Glitch&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Exploring and implementing the various implementation details of these was a truly significant lift by &lt;a class="mentioned-user" href="https://dev.to/0vortex"&gt;@0vortex&lt;/a&gt;, and it shows in how he listed out the pros and cons of each Cloud IDE in our &lt;a href="https://github.com/open-sauced/open-sauced#-prerequisites"&gt;README&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One might argue that support for each Cloud IDE should have been its own PR, but I would point out that sometimes it's better to let the technical details agglomerate so that the ancillary benefits of a major change follow directly on the heels of the core benefits. I was personally very affirmed when a contributor was able to move forward with a contribution shortly after this PR landed!&lt;/p&gt;

&lt;p&gt;Based on our experience at present, Stackblitz, Replit, Codesandbox, and Glitch are not reliable enough to test significant feature contributions to an application at the scale of Open Sauced. From what we see, the reliability challenges deal with the virtual filesystems in use - Open Sauced is a five year old project, and the codebase has grown. In fact, we feel that the performance benefits of Vite (especially its use of &lt;a href="https://esbuild.github.io/"&gt;esbuild&lt;/a&gt;) made it possible for us to get the Cloud IDE support to the level that it is today.  &lt;/p&gt;

&lt;p&gt;Let us know in the comments if you'd to see more technical detail about our experiences with the Cloud IDEs!&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@ismailenesayhan?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;İsmail Enes Ayhan&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/server-rack?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>git</category>
    </item>
    <item>
      <title>Converting to Vite (Part 3)</title>
      <dc:creator>Matthew Foley</dc:creator>
      <pubDate>Thu, 27 Jan 2022 15:39:21 +0000</pubDate>
      <link>https://dev.to/opensauced/converting-to-vite-part-3-4hg4</link>
      <guid>https://dev.to/opensauced/converting-to-vite-part-3-4hg4</guid>
      <description>&lt;p&gt;In Part 3 of this series, we'll talk about our use of various plugins for &lt;a href="https://vitejs.dev"&gt;Vite&lt;/a&gt; on the &lt;a href="https://github.com/open-sauced/open-sauced"&gt;Open Sauced project&lt;/a&gt;. Vite provides extensibility in the form of a &lt;a href="https://vitejs.dev/guide/api-plugin.html"&gt;Plugin API&lt;/a&gt;, based on that of &lt;a href="https://rollupjs.org/guide/en/"&gt;Rollup&lt;/a&gt;. For reference on which Rollup plugins Vite is compatible with (and to what degree), see &lt;a href="https://vite-rollup-plugins.patak.dev/"&gt;Vite Rollup Plugins&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once we were able to get things realigned with our dependencies and we were able to get Vite to build everything correctly for the simplest cases (production build on browsers supporting ESM), we shifted our focus to restoring tooling feature parity to what we had with &lt;a href="https://webpack.js.org/"&gt;Webpack&lt;/a&gt; (or at least the parts we cared about). Frankly these were some things that I personally wasn't intimately familiar with, so the vast majority of configuring Vite plugins was done by &lt;a class="mentioned-user" href="https://dev.to/0vortex"&gt;@0vortex&lt;/a&gt;. That said, the easiest way for me to talk about this is to just refer to the imports section of our &lt;code&gt;vite.config.ts&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ViteReact&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ViteEslint&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nabla/vite-plugin-eslint&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ViteHtml&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite-plugin-html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ViteInspect&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite-plugin-inspect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ViteLegacy&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vitejs/plugin-legacy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;VitePWA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;VitePWAOptions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite-plugin-pwa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ViteReplace&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@rollup/plugin-replace&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ViteTimeReporter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite-plugin-time-reporter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ViteVisualizer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rollup-plugin-visualizer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you might guess, the &lt;a href="https://www.npmjs.com/package/@vitejs/plugin-react"&gt;@vitejs/plugin-react&lt;/a&gt; plugin is the one most directly responsible for getting Open Sauced to build in Vite, generally.&lt;/p&gt;

&lt;p&gt;We make use of &lt;code&gt;eslint&lt;/code&gt; in the Open Sauced project, and it had been part of the Webpack build steps. To reach feature parity on this, we made use of &lt;a href="https://www.npmjs.com/package/@nabla/vite-plugin-eslint"&gt;@nabla/vite-plugin-eslint&lt;/a&gt;. As mentioned on the plugin's NPM page, it "keeps HMR fast: linting is done asynchronously and doesn't block the transform process."&lt;/p&gt;

&lt;p&gt;We make use of the &lt;a href="https://www.npmjs.com/package/vite-plugin-html"&gt;ViteHtml&lt;/a&gt; plugin to inject our app version into the page title.  Actually, this wasn't part of our original build process, but we like it now!&lt;/p&gt;

&lt;p&gt;We make use of the &lt;a href="https://www.npmjs.com/package/vite-plugin-inspect"&gt;ViteInspect&lt;/a&gt; plugin for development purposes in optimizing Vite. This plugin lets us observe the state of the various Vite plugins. &lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.npmjs.com/package/@vitejs/plugin-legacy"&gt;ViteLegacy&lt;/a&gt; plugin is what we use to target browsers not supporting ES Modules. &lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.npmjs.com/package/vite-plugin-pwa"&gt;Vite PWA&lt;/a&gt; plugin was the one I mentioned in Part 2 - we worked a bit to to get our existing PWA implementation working, and we wound up deciding to transfer to use of this plugin instead.&lt;/p&gt;

&lt;p&gt;Proving the use case of supporting the same effective Plugins API as Rollup, we are using &lt;a href="https://www.npmjs.com/package/@rollup/plugin-replace"&gt;@rollup/plugin-replace&lt;/a&gt; to inject the Netlify build date into a Footer react component.&lt;/p&gt;

&lt;p&gt;For vanity metrics, we use &lt;a href="https://www.npmjs.com/package/vite-plugin-time-reporter"&gt;vite-plugin-time-reporter&lt;/a&gt; in order to gloat about build times.&lt;/p&gt;

&lt;p&gt;In yet another showcase of Rollup plugin compatibility (and this one's my favorite), we are using &lt;a href="https://www.npmjs.com/package/rollup-plugin-visualizer"&gt;rollup-plugin-visualizer&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Some of the plugins are loaded unconditionally, and others are loaded based on build context (I'll talk a little more about this in Part 4). Below is a snippet from our &lt;code&gt;vite.config.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;ViteTimeReporter&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;ViteEslint&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;ViteInspect&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;ViteReact&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;fastRefresh&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isTest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// Exclude storybook stories&lt;/span&gt;
    &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt;stories&lt;/span&gt;&lt;span class="se"&gt;\.(&lt;/span&gt;&lt;span class="sr"&gt;t|j&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;sx&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// Only .jsx files&lt;/span&gt;
    &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;**/*.jsx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;babel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;babel-plugin-styled-components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="nx"&gt;ViteHtml&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;minify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isProd&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isBuild&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Open Sauced v&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;npm_package_version&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's a snippet of some code used for conditional application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;isBuild&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isLegacy&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;ViteLegacy&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;defaults&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;not IE 11&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;isReport&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;ViteVisualizer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./build/bundle.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;open&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;gzipSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'd love to hear in the comments what some of your favorite plugins are for Vite (or Rollup)!&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/@nugthan?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Nathan Watson&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/block-diagram?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>vite</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Converting to Vite (Part 2)</title>
      <dc:creator>Matthew Foley</dc:creator>
      <pubDate>Thu, 13 Jan 2022 16:08:35 +0000</pubDate>
      <link>https://dev.to/opensauced/converting-to-vite-part-2-3li0</link>
      <guid>https://dev.to/opensauced/converting-to-vite-part-2-3li0</guid>
      <description>&lt;p&gt;In this post, I'm going to describe some of the snags that we encountered as we transitioned to Vite - at their best, snags become lessons!&lt;/p&gt;

&lt;p&gt;Open Sauced is a Progressive Web Application (PWA), and this includes the use of a Service Worker.  In my personal understanding, a Service Worker definition should be packaged as a standalone JavaScript file. When you look at how bundling is done in Vite, it will generate a &lt;code&gt;vendor.xyz.js&lt;/code&gt; file, an &lt;code&gt;index.xyz.js&lt;/code&gt; file, and otherwise pass through static assets in the &lt;code&gt;public&lt;/code&gt; directory as-is. Our webpack configuration on the other hand was configured to handle our &lt;code&gt;src/service-worker.js&lt;/code&gt; in a specific way. For that reason, we needed to move our &lt;code&gt;src/service-worker.js&lt;/code&gt; file to &lt;code&gt;public/service-worker.js&lt;/code&gt;, and move around the associations in our &lt;code&gt;src/index.js&lt;/code&gt; file. Another thing we had to learn about was the way Vite handles &lt;a href="https://vitejs.dev/guide/env-and-mode.html"&gt;environment variables&lt;/a&gt;.  Our application would look at whether the application was in production or development mode (and also whether it was being served locally) in order to decide whether to register the service worker. For a project using Webpack, you usually refer to these as &lt;code&gt;process.env.VARIABLE&lt;/code&gt; and the value is statically set in the bundling process. Vite does something a bit different, but instead you would need to refer to &lt;code&gt;import.meta.env.VARIABLE&lt;/code&gt; and only a handful of things are pre-set for you and otherwise you need to use a variable naming convention to have something statically included in the bundle. Fortunately, most of the variables we needed to use were included by default, so it was easy to get working (or so we thought). We tweaked and tweaked some more, and in the end, we just ended up using the &lt;a href="https://github.com/antfu/vite-plugin-pwa"&gt;&lt;code&gt;vite-plugin-pwa&lt;/code&gt;&lt;/a&gt; extension to handle everything, while moving most of our PWA manifest to &lt;code&gt;vite.config.ts&lt;/code&gt;. It's great to know how things work under the hood, but sometimes you just get better results with a plugin!&lt;/p&gt;

&lt;p&gt;Another thing that we ran into dealt with the fact that some libraries end up just a little bit differently in development bundling than in production bundling.  When developing, Vite takes advantage of ESM to let the browser effectively cache your dependencies, separated out into module files.  In production, everything is bundled into one vendor file. Libraries can export different compiled versions between these two situations. We were having a lot of trouble that we isolated down to a specific component, that in turn used the &lt;code&gt;react-markdown&lt;/code&gt; library. After reading through &lt;a href="https://github.com/vitejs/vite/issues/3592"&gt;issues&lt;/a&gt; for this one and its dependencies, we found that there was a circular reference in one of &lt;code&gt;react-markdown&lt;/code&gt;'s dependencies that only showed up in production bundles. &lt;/p&gt;

&lt;p&gt;The most straightforward fix for the circular reference was to update &lt;code&gt;react-markdown&lt;/code&gt; through one major revision, but this introduced a new snag.  In this major revision, &lt;code&gt;react-markdown&lt;/code&gt; changed to &lt;a href="https://github.com/remarkjs/react-markdown/blob/main/changelog.md#700---2021-08-13"&gt;ESM only&lt;/a&gt;, which would be fine for Vite, but not for our testing approach for &lt;code&gt;jest&lt;/code&gt; (other than experimentally, &lt;a href="https://jestjs.io/docs/ecmascript-modules"&gt;so I learned&lt;/a&gt;. &lt;a class="mentioned-user" href="https://dev.to/0vortex"&gt;@0vortex&lt;/a&gt; and I got some help from &lt;a class="mentioned-user" href="https://dev.to/jasonericdavis"&gt;@jasonericdavis&lt;/a&gt; on Discord to mock the &lt;code&gt;react-markdown&lt;/code&gt; component in Jest (bypassing the need for ESM support) as part of a &lt;a href="https://github.com/open-sauced/open-sauced/pull/1333"&gt;preparatory PR&lt;/a&gt;, and we got back on track.&lt;/p&gt;

&lt;p&gt;One takeaway that I had from this was the practice of stepping beyond running &lt;code&gt;vite dev&lt;/code&gt;, and running &lt;code&gt;vite build&lt;/code&gt; and &lt;code&gt;vite preview&lt;/code&gt; as well, in order to verify what would run in production. We use Netlify deploy previews in Open Sauced, and running both &lt;code&gt;vite build&lt;/code&gt; and &lt;code&gt;vite preview&lt;/code&gt; helps with reproducing production issues locally. We updated our &lt;code&gt;package.json&lt;/code&gt; to reflect these &lt;a href="https://vitejs.dev/guide/#command-line-interface"&gt;CLI commands&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I would love to hear from others what kind of experience they had switching from Webpack to Vite!&lt;/p&gt;

&lt;p&gt;&lt;small&gt;&lt;em&gt;Cover image Photo by &lt;a href="https://unsplash.com/@william07?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;william william&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/container-ship?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;. I chose this one because I felt like &lt;a class="mentioned-user" href="https://dev.to/0vortex"&gt;@0vortex&lt;/a&gt; and I were the tugboats!&lt;/em&gt;&lt;/small&gt;&lt;/p&gt;

</description>
      <category>webpack</category>
      <category>vite</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Converting to Vite (Part 1)</title>
      <dc:creator>Matthew Foley</dc:creator>
      <pubDate>Wed, 05 Jan 2022 16:41:57 +0000</pubDate>
      <link>https://dev.to/opensauced/converting-to-vite-part-1-4ff4</link>
      <guid>https://dev.to/opensauced/converting-to-vite-part-1-4ff4</guid>
      <description>&lt;p&gt;This is Part 1 of a series about how recently in &lt;a href="https://opensauced.pizza"&gt;Open Sauced&lt;/a&gt;, we converted the project from using Webpack v4 to using &lt;a href="https://vitejs.dev"&gt;Vite&lt;/a&gt;! A lot of what we'll cover in this series deals with &lt;a href="https://github.com/open-sauced/open-sauced/pull/1322"&gt;PR #1322&lt;/a&gt;. &lt;a class="mentioned-user" href="https://dev.to/bdougieyo"&gt;@bdougieyo&lt;/a&gt; started this as a &lt;code&gt;create-react-app&lt;/code&gt; project 5+ years ago and so this conversion certainly turned out to be an undertaking!&lt;/p&gt;

&lt;p&gt;You can read in many different places about the benefits of using Vite for tooling, as well as how it works under the hood, but we can unequivocally tell you that it significantly improved on the build times for our project. My fellow contributor &lt;a class="mentioned-user" href="https://dev.to/0vortex"&gt;@0vortex&lt;/a&gt; spent plenty of time with this PR, and he observed going from build times with Webpack around 220 seconds, to full build times with Vite around 9 seconds (and hot module reloads measured in milliseconds at worst).&lt;/p&gt;

&lt;p&gt;So how did we get here? &lt;strong&gt;Well, it's a good thing to describe alternatives considered when you add issues to a repo!&lt;/strong&gt; Months ago, &lt;a class="mentioned-user" href="https://dev.to/0vortex"&gt;@0vortex&lt;/a&gt; described in &lt;a href="https://github.com/open-sauced/open-sauced/issues/1131"&gt;Issue #1131&lt;/a&gt; some opportunities for dependency updates that would require version 5 of webpack with our webpack configuration, and warned that the dependency management would probably be tricky. I fixated on an alternative that he mentioned about converting the project to use &lt;a href="https://www.snowpack.dev/"&gt;Snowpack&lt;/a&gt;. I had wanted to learn more about bundling tools, so I took a few days here and there after Thanksgiving and got Open Sauced mostly working with it (see &lt;a href="https://github.com/open-sauced/open-sauced/pull/1320"&gt;PR #1320&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/bdougieyo"&gt;@bdougieyo&lt;/a&gt; looked over that PR on &lt;a href="https://twitch.tv/bdougieYO"&gt;stream&lt;/a&gt;, and pointed out that there was a lot more momentum recently with Vite as opposed to Snowpack. He pointed out that &lt;a href="https://astro.build"&gt;Astro&lt;/a&gt; was changing from using &lt;a href="https://astro.build/blog/astro-021-preview/"&gt;Snowpack to Vite&lt;/a&gt; for bundling, and that these were the same folks responsible for Snowpack. &lt;/p&gt;

&lt;p&gt;As it turned out, the conversion steps for getting our project working with Vite were pretty similar to those for Snowpack, so I managed to get a branch &lt;em&gt;mostly working&lt;/em&gt; with Vite in about 25 minutes while the stream was still going. Little did I know, there was still plenty to be done!&lt;/p&gt;

&lt;p&gt;In Part 2 of this series, I'll talk about some of the snags and learnings we had with the conversion, and in Parts 3 and 4, I'll talk about some of the ways the scope for this PR grew.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover Image by &lt;a href="https://unsplash.com/@andersjilden?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Anders Jildén&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/fast?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vite</category>
      <category>webdev</category>
      <category>tooling</category>
      <category>react</category>
    </item>
    <item>
      <title>Highlighting: sync-contribution-graph</title>
      <dc:creator>Matthew Foley</dc:creator>
      <pubDate>Wed, 29 Dec 2021 20:39:25 +0000</pubDate>
      <link>https://dev.to/mtfoley/highlighting-sync-contribution-graph-6o8</link>
      <guid>https://dev.to/mtfoley/highlighting-sync-contribution-graph-6o8</guid>
      <description>&lt;p&gt;A couple of weeks ago, I nearly scrolled past this gem on my twitter feed: &lt;a href="https://github.com/kefimochi/sync-contribution-graph"&gt;sync-contribution-graph&lt;/a&gt;, by &lt;a class="mentioned-user" href="https://dev.to/kefimochi"&gt;@kefimochi&lt;/a&gt;. Go have a look! &lt;/p&gt;

&lt;p&gt;You can use this tool to have your GitHub contribution graph accurately reflect contributions from other accounts you make use of. For example, outside of work I use the handle &lt;a href="https://github.com/mtfoley"&gt;mtfoley&lt;/a&gt;, but I have a separate account I use for my job. I like the idea that I could use this to accurately reflect my activity level, and that no private information about that work handle is revealed.&lt;/p&gt;

&lt;p&gt;The way it works is pretty straightforward.  When you configure it with a username and a time frame (year), it performs an HTTP request to the appropriate URL, and parses the HTML in the response for the dates/counts of contributions (these correspond to those little green squares).  Based on this data, it creates appropriate &lt;code&gt;git&lt;/code&gt; shell commands. The shell commands are saved to a file that can optionally be run immediately. Here's a snippet that's the meat of it in &lt;a href="https://github.com/kefimochi/sync-contribution-graph/blob/main/src/index.js"&gt;src/index.js&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node-html-parser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;shell&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shelljs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="c1"&gt;// Gathers needed git commands for bash to execute per provided contribution data.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getCommand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contribution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`GIT_AUTHOR_DATE=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;contribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;T12:00:00 GIT_COMMITER_DATE=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;contribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;T12:00:00 git commit --allow-empty -m "Rewriting History!" &amp;gt; /dev/null\n`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;contribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Returns contribution graph html for a full selected year.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`https://github.com/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/contributions?tab=overview&amp;amp;from=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-12-01&amp;amp;to=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-12-31`&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;


  &lt;span class="c1"&gt;// Retrieves needed data from the html, loops over green squares with 1+ contributions,&lt;/span&gt;
  &lt;span class="c1"&gt;// and produces a multi-line string that can be run as a bash command.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[data-count]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data-count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;contribution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;contribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;contribution&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;getCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contribution&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;git pull origin main&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;git push -f origin main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;script.sh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;File was created successfully.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This might take a moment!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sh ./script.sh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I made some suggestions in the setup workflow on the repo and submitted a &lt;a href="https://github.com/kefimochi/sync-contribution-graph/pull/8"&gt;PR to update the README&lt;/a&gt;.  I hope you find this and other work by &lt;a class="mentioned-user" href="https://dev.to/kefimochi"&gt;@kefimochi&lt;/a&gt; to be of interest!&lt;/p&gt;

</description>
      <category>github</category>
      <category>javascript</category>
      <category>bash</category>
      <category>git</category>
    </item>
    <item>
      <title>My first contribution to prometheus</title>
      <dc:creator>Matthew Foley</dc:creator>
      <pubDate>Wed, 22 Dec 2021 16:41:41 +0000</pubDate>
      <link>https://dev.to/mtfoley/my-first-contribution-to-prometheus-np1</link>
      <guid>https://dev.to/mtfoley/my-first-contribution-to-prometheus-np1</guid>
      <description>&lt;p&gt;Several weeks ago I joined &lt;a href="https://virtualcoffee.io"&gt;Virtual Coffee&lt;/a&gt;, and I really love that community.  I shared during one of the weekly sessions that I was hoping to learn some more about backend by contributing to open source software.  One of the more seasoned members suggested that I try contributing to &lt;a href="https://github.com/prometheus/prometheus"&gt;prometheus/prometheus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Taken from the description on the repo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prometheus, a Cloud Native Computing Foundation project, is a systems and service monitoring system. It collects metrics from configured targets at given intervals, evaluates rule expressions, displays the results, and can trigger alerts when specified conditions are observed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As I started looking at the project issues, I didn't find many good first issues that I personally felt comfortable with, so I decided to take advantage that I had a completely fresh set of eyes on the project! As I followed along with the &lt;a href="https://prometheus.io/docs/prometheus/latest/getting_started/"&gt;Getting Started guide&lt;/a&gt;, something immediately jumped out at me! When opening &lt;code&gt;http://localhost:9090/metrics&lt;/code&gt; and opening the Metrics Explorer, I was presented with a really long list of metrics that I could view the time series data for.  I thought to myself "with such a long list, it would be nice if there was a search field!" I opened an &lt;a href="https://github.com/prometheus/prometheus/issues/9628"&gt;issue&lt;/a&gt; about this, and then a subsequent &lt;a href="https://github.com/prometheus/prometheus/pull/9629"&gt;pull request&lt;/a&gt;. Here's a screenshot of at least the first iteration of what I implemented:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gbRghfZU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tvc2khzvdo56jql7xv9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gbRghfZU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tvc2khzvdo56jql7xv9f.png" alt="screenshot of metrics search feature" width="880" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This project uses &lt;a href="https://probot.github.io/apps/dco/"&gt;Developer Certificate of Origin (DCO)&lt;/a&gt; as one of the checks it does for PR. This makes sure that all commits are signed off to include the contributors name and email address. I learned the hard way about amending commits and using &lt;code&gt;git commit -s&lt;/code&gt; to sign off commits.&lt;/p&gt;

&lt;p&gt;Beyond that, the reviewer GitHub user @juliusv was very friendly and engaging and asked me to implement the use of Fuzzy search with &lt;a href="https://www.npmjs.com/package/@nexucis/fuzzy"&gt;@nexucis/fuzzy&lt;/a&gt;, which had been used on an adjacent component.  I was also able to add appropriate tests for the new component! &lt;/p&gt;

&lt;p&gt;Since this PR, I've gotten a couple more merged to the project, including some contribution to the &lt;a href="https://go.dev/"&gt;Go&lt;/a&gt; codebase, so I'm starting to dig into the backend side which is what I had wanted to do!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover image by &lt;a href="https://unsplash.com/@77timon"&gt;Timon Wanner&lt;/a&gt;. Picked it on account of the story of &lt;a href="https://en.wikipedia.org/wiki/Prometheushttps://en.wikipedia.org/wiki/Prometheus"&gt;Prometheus&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>javascript</category>
      <category>react</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Implementing Dark Mode (Part 3)</title>
      <dc:creator>Matthew Foley</dc:creator>
      <pubDate>Thu, 16 Dec 2021 15:57:20 +0000</pubDate>
      <link>https://dev.to/opensauced/implementing-dark-mode-part-3-5gn</link>
      <guid>https://dev.to/opensauced/implementing-dark-mode-part-3-5gn</guid>
      <description>&lt;p&gt;In contributing to Open Sauced and other OSS projects as well, I've found time and time again that there are such ample opportunities to learn.  However, contributing a feature and sticking with it on a longer term can cause those opportunities to multiply!  In Part 3 of this series, I'm going to talk about some of the after-effects of implementing dark mode on Open Sauced in &lt;a href="https://github.com/open-sauced/open-sauced/pull/1020"&gt;PR #1020&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It was around this time that &lt;a class="mentioned-user" href="https://dev.to/bdougieyo"&gt;@bdougieyo&lt;/a&gt; had really been wanting to flesh out the existing documentation. In the interest of keeping the project moving, the PR was merged with the caveat that we needed to make sure it was well documented so future contributors could work with it. &lt;/p&gt;

&lt;p&gt;Seeing as this PR had a big impact on look and feel of the app, and touched so many files, it's not surprising there were 32 comments on the PR when it was all said and done.  Some of those were scoping the feature, some of them were thinking critically about colors, and some of them were talking about the approach in general (i.e. code review). To have this much commentary in the PR made it really easy to document the feature! The opportunity to learn and contribute multiplied and that brings us to a follow-on &lt;a href="https://github.com/open-sauced/open-sauced/pull/1036"&gt;documentation PR&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A more obvious case of learning opportunities multiplying is the fact that having authored the feature, you'd be pretty well suited to make little fixes to it (and there will be little fixes needed). Case in point, there was an &lt;a href="https://github.com/open-sauced/open-sauced/issues/1045"&gt;issue filed&lt;/a&gt; by &lt;a class="mentioned-user" href="https://dev.to/0vortex"&gt;@0vortex&lt;/a&gt; where the hover style for some components still had light coloring and this made the text unreadable in dark mode. I  loved reading his issue description of &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hovering over a repository in the dashboard gives a user a surprise sunburn. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Having learned some of the syntax for styled components and knowing how they were organized in the project, I was able to make a subtle but easy fix in &lt;a href="https://github.com/open-sauced/open-sauced/pull/1060"&gt;PR #1060&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Last point I'll make here, the feature you author might reach further than you think. Looking back now, it was fairly obvious that our design system for Open Sauced (&lt;a href="https://storybook.js.org"&gt;Storybook&lt;/a&gt;) should allow toggling dark mode. What was not obvious was how to make all that work.  Storybook supports this conceptually but in a newer version than we had. I did a lot of learning as I worked on  &lt;a href="https://github.com/open-sauced/open-sauced/pull/1061"&gt;PR #1061&lt;/a&gt; to get it up and running, since I didn't have a lot of experience with dependency updates in a React app. &lt;/p&gt;

&lt;p&gt;Learning with a goal in mind is powerful, and sticking with features you contribute can supercharge your learning because the goals multiply!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Implementing Dark Mode (Part 2)</title>
      <dc:creator>Matthew Foley</dc:creator>
      <pubDate>Thu, 09 Dec 2021 15:36:38 +0000</pubDate>
      <link>https://dev.to/opensauced/implementing-dark-mode-part-2-2lip</link>
      <guid>https://dev.to/opensauced/implementing-dark-mode-part-2-2lip</guid>
      <description>&lt;p&gt;This is Part 2 of the series on Implementing Dark Mode. This was done in &lt;a href="https://github.com/open-sauced/open-sauced/pull/1020"&gt;open-sauced/open-sauced#1020&lt;/a&gt;, and handily demonstrated to me the wealth of learning opportunities in contributing to Open Source. I for one have learned a ton! On this one, I got the opportunity for learning in several areas. I was still pretty new to React (and I still am), so I had not yet used the &lt;a href="https://reactjs.org/docs/context.html"&gt;Context API&lt;/a&gt;.  For a lot of the same reasons, I hadn't used the &lt;a href="https://styled-components.com/"&gt;styled-components&lt;/a&gt; library before. &lt;/p&gt;

&lt;p&gt;Throughout the rest of these points, the thing to bear in mind is that for the most part, the app being in dark mode just means that the HTML &lt;code&gt;body&lt;/code&gt; element has a CSS class name including "dark". &lt;/p&gt;

&lt;p&gt;One implementation detail that I feel was a win was that the only React component that had any kind of interaction with the ThemeContext was a set of buttons that toggle the theme.  I like to think this helps with separation of concerns. Here's a code snippet from the buttons component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ThemeContext&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../ThemeContext&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;FlexCenter&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../styles/Grid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;darkMode&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../images/darkMode.svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;lightMode&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../images/lightMode.svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;themeAuto&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../images/themeAuto.svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ThemeButtonGroup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ThemeContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;FlexCenter&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;marginRight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.5rem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;
        &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0 .5rem&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
          &lt;span class="nx"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt;
          &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;darkMode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
          &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"dark mode"&lt;/span&gt; 
          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
            &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#ccc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
            &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;transparent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
// ...
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;FlexCenter&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another implementation detail was related to coloring of images. Open Sauced makes use of many SVG images, of differing flavors. In the cases where SVG files are in the static assets of Open Sauced (e.g. &lt;code&gt;&amp;lt;img alt="open sauced" className="svg" src={mortarBoard} /&amp;gt;&lt;/code&gt;), the coloring of these is controlled using the &lt;code&gt;filter&lt;/code&gt; CSS property. On the other hand, we also make use of &lt;a href="https://github.com/primer/octicons"&gt;@primer/octicons-react&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Here's a sample of one of these icons in component code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;SearchIcon&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@primer/octicons-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SearchIcon&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"large"&lt;/span&gt; &lt;span class="na"&gt;verticalAlign&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"middle"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"svg"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These inject code directly into markup as &lt;code&gt;&amp;lt;svg&amp;gt;...&amp;lt;/svg&amp;gt;&lt;/code&gt;, requiring use of CSS property &lt;code&gt;fill&lt;/code&gt;.&lt;br&gt;
Finally here's the CSS code snippet where the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; tags are handled differently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="nc"&gt;.dark&lt;/span&gt; &lt;span class="nt"&gt;img&lt;/span&gt;&lt;span class="nc"&gt;.svg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;invert&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="nc"&gt;.dark&lt;/span&gt; &lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="nc"&gt;.svg&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--lightestGrey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I referred quite a bit to this article: &lt;a href="https://medium.com/@union_io/swapping-fill-color-on-image-tag-svgs-using-css-filters-fa4818bf7ec6"&gt;Color Control of SVGs&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;One last fun implementation detail was working with our use of &lt;a href="https://github.com/dvtng/react-loading-skeleton"&gt;react-loading-skeleton&lt;/a&gt; (I love this effect, and I feel it really does work in keeping the user engaged and under the impression of the app working while data loads).   To make this effect still work well in dark mode, I took the opportunity to crack open the source, and replicate a few key values as found in this snippet of our CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="nc"&gt;.dark&lt;/span&gt; &lt;span class="nc"&gt;.react-loading-skeleton&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;backgroundGrey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;linear-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="m"&gt;90deg&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;backgroundGrey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;grey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;backgroundGrey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, working on this PR really cemented my personal belief and experience that contributing to Open Source Software can provide amazing opportunities for learning by doing!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>javascript</category>
      <category>css</category>
      <category>react</category>
    </item>
    <item>
      <title>Implementing Dark Mode (Part 1)</title>
      <dc:creator>Matthew Foley</dc:creator>
      <pubDate>Tue, 16 Nov 2021 15:34:47 +0000</pubDate>
      <link>https://dev.to/opensauced/implementing-dark-mode-part-1-3ono</link>
      <guid>https://dev.to/opensauced/implementing-dark-mode-part-1-3ono</guid>
      <description>&lt;p&gt;I'd like to share the story behind one of my favorite contributions to Open Sauced so far, which is the addition of "Dark Mode", &lt;a href="https://github.com/open-sauced/open-sauced/pull/1020"&gt;PR #1020&lt;/a&gt;. This PR touched 25 files and was pretty substantial in scope, so I'm going to break this up into 3 parts. Part 1 is here is just the background - the what and the why, as &lt;a class="mentioned-user" href="https://dev.to/bdougieyo"&gt;@bdougieyo&lt;/a&gt; sometimes says. If there's one takeaway though, it's the value of opening a PR early in your process - you can share your progress and your roadblocks, and maintainers can help you get unblocked!&lt;/p&gt;

&lt;p&gt;With that, the original idea for the dark mode feature came from &lt;a class="mentioned-user" href="https://dev.to/filiptronicek"&gt;@filiptronicek&lt;/a&gt; in &lt;a href="https://github.com/open-sauced/open-sauced/issues/607"&gt;Issue #607&lt;/a&gt;, and I decided to try to take this one on for a few reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1) I'd read an article once about &lt;code&gt;prefers-color-scheme&lt;/code&gt;, and that was my level of knowledge about dark mode.&lt;/li&gt;
&lt;li&gt;2) I wanted to learn the ins and outs of how the project handled styles.&lt;/li&gt;
&lt;li&gt;3) My Macbook was set for the color preference following the time of day, so based on #1, I knew I was going to test the feature with (literally) endless delight!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this project I picked up a habit of starting talking about the PR relatively early in the cycle. So as I got started on things, I had inferred that the intention was to fall back to the system preference but that the user could override it to either or light or dark mode and have that setting persisted to local storage. The more I read articles, the more I saw a pattern that they either just simply followed the system preference, or they would start with a default and toggle back and forth. So there were some cases using a single state for user preference, and some with two states, but none with three states. &lt;/p&gt;

&lt;p&gt;Talking with other contributors about it, &lt;a class="mentioned-user" href="https://dev.to/0vortex"&gt;@0vortex&lt;/a&gt; pointed out a &lt;a href="https://stackoverflow.blog/2020/03/31/building-dark-mode-on-stack-overflow/"&gt;post on the StackOverflow blog&lt;/a&gt;, and it talked in passing about a three-state solution. I was sold! I felt compelled to see this thing through with a three-state solution, and I'm glad I did because since then I've seen a handful of blog posts and examples in the wild, which I really like.&lt;/p&gt;

&lt;p&gt;Stay tuned for Part 2 where I'll cover some implementation details and learnings, and Part 3 were I'll cover some of the unexpected things about this PR!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>because copy &amp; paste is tough</title>
      <dc:creator>Matthew Foley</dc:creator>
      <pubDate>Tue, 09 Nov 2021 17:05:32 +0000</pubDate>
      <link>https://dev.to/mtfoley/because-copy-paste-is-tough-3f3o</link>
      <guid>https://dev.to/mtfoley/because-copy-paste-is-tough-3f3o</guid>
      <description>&lt;p&gt;&lt;a href="https://i.giphy.com/media/arp7Pkw2fmdwc/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/arp7Pkw2fmdwc/giphy.gif" alt="copy and paste is tough"&gt;&lt;/a&gt;&lt;br&gt;
Following up on my &lt;a href="https://dev.to/mtfoley/sifting-thru-the-types-5e2p"&gt;post last week&lt;/a&gt; about the first aspect of &lt;a href="https://github.com/open-sauced/explore.opensauced.pizza/pull/2" rel="noopener noreferrer"&gt;a PR&lt;/a&gt; contribution to &lt;a href="//open-sauced/explore.opensauced.pizza"&gt;explore.opensauced.pizza&lt;/a&gt;, I'm going to talk about the second aspect of that PR - joyfully implemented as an HTML &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; element (I really like these).&lt;/p&gt;

&lt;p&gt;So as I mentioned in the post before:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We also wanted to let users quickly reproduce the queries we use in Open Sauced... this way, when its time to iterate on an existing feature, there's very little friction to finding that starting point.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;About a week before this, I had been working on a &lt;a href="https://github.com/open-sauced/open-sauced/pull/1101" rel="noopener noreferrer"&gt;PR&lt;/a&gt; for tabulating the GraphQL API calls in the Open Sauced docs, so a lot of the details about API calls were pretty fresh. &lt;/p&gt;

&lt;p&gt;Side note, if you want line breaks inside a table in markdown, you'll need to use a &lt;code&gt;&amp;lt;br/&amp;gt;&lt;/code&gt; element, but don't forget to use a self closing tag in the event your markdown file is parsed and used by a tool like Docusaurus, &lt;a href="https://github.com/open-sauced/open-sauced/pull/1104" rel="noopener noreferrer"&gt;:cough, cough:&lt;/a&gt;. Shout out to &lt;a class="mentioned-user" href="https://dev.to/0vortex"&gt;@0vortex&lt;/a&gt; for cleaning up my messes!&lt;/p&gt;

&lt;p&gt;Anywho, after looking around at GraphiQL implementations, I came to the belief that most define a fetcher with the correct API endpoint/headers and otherwise things just work out of the box.  Once the introspection query is run and the schema parsed and validated, the combination of the Explorer pane and the Query Editor pane make it really easy to build up and run valid queries. There's also a common pattern of using a default query so when the client first loads up, the query is pre-populated. What these two don't help with is reproducing and working with &lt;em&gt;multiple&lt;/em&gt; queries.&lt;/p&gt;

&lt;p&gt;The approach I wound up taking was to store all of the dynamic queries in an object, and then generate a &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; element in the toolbar, which updates the query contents and query name with the &lt;code&gt;onchange&lt;/code&gt; event. Here's the piece of code that does the job...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GraphiQL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Toolbar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt;
        &lt;span class="na"&gt;defaultValue&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handleEditQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Queries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handleEditOperationName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Choose a Query&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Queries&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ALL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isMutation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Queries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mutation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isMutation&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(Mutation) &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;select&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    // ...
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;GraphiQL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Toolbar&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's a screenshot of what it does.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4il1y1gya6le6eptok8a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4il1y1gya6le6eptok8a.png" alt="graphiql screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The thing I still want to see work for this repo is supporting persisted queries - really just for the &lt;a href="https://docs.opensauced.pizza/technical/fetching-data-from-github/#use-of-api-in-components" rel="noopener noreferrer"&gt;sake of completeness&lt;/a&gt;.  I have some ideas on how to do it, but perhaps someone reading has done this before?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>sifting thru the types</title>
      <dc:creator>Matthew Foley</dc:creator>
      <pubDate>Fri, 05 Nov 2021 14:33:21 +0000</pubDate>
      <link>https://dev.to/mtfoley/sifting-thru-the-types-5e2p</link>
      <guid>https://dev.to/mtfoley/sifting-thru-the-types-5e2p</guid>
      <description>&lt;p&gt;Flow state is a rare treat for me these days. The last time I can remember being in that zone was working on a &lt;a href="https://github.com/graphql/graphiql" rel="noopener noreferrer"&gt;GraphiQL&lt;/a&gt; implementation for Open Sauced, &lt;a href="https://explore.opensauced.pizza" rel="noopener noreferrer"&gt;https://explore.opensauced.pizza&lt;/a&gt;. The Open Sauced project makes use of &lt;a href="https://onegraph.com" rel="noopener noreferrer"&gt;OneGraph&lt;/a&gt;, to handle authentication and persisted query features in working with the &lt;a href="https://docs.github.com/en/graphql" rel="noopener noreferrer"&gt;GitHub GraphQL API&lt;/a&gt;. This was the first I had worked on any kind of GraphiQL implementation, so for those of you at the point I was at then, GraphiQL is an Open Source project that can be used to interact with a GraphQL API in an ad-hoc and dynamic way, allowing a developer to iterate quickly on features from a data retrieval standpoint. This post is about the &lt;a href="https://github.com/open-sauced/explore.opensauced.pizza/pull/2" rel="noopener noreferrer"&gt;PR #2&lt;/a&gt; in the repo.&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/0vortex"&gt;@0vortex&lt;/a&gt; had laid a lot of the groundwork for this implementation and as he brought myself and &lt;a class="mentioned-user" href="https://dev.to/bdougieyo"&gt;@bdougieyo&lt;/a&gt; up to speed on the where things were at, the problem to solve was having too much stuff to interact with.  OneGraph brings a lot of value to the table in working with GraphQL, and this is evident in the number and breadth of APIs that it works with. For some reference, take a look at this image (or play with their GraphiQL tool). &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qutuu4v0j37sf7asndp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qutuu4v0j37sf7asndp.png" alt="OneGraph GraphiQL Screenshot"&gt;&lt;/a&gt;&lt;br&gt;
The vision for &lt;a href="https://explore.opensauced.pizza" rel="noopener noreferrer"&gt;https://explore.opensauced.pizza&lt;/a&gt; was to have a rapid prototyping tool &lt;em&gt;specific to Open Sauced&lt;/em&gt;, and that's why having all these other services in the explorer tool is too much. We also wanted to let users quickly reproduce the queries we use in Open Sauced so that when a feature calls for an adjustment - this way, when its time to iterate on an existing feature, there's very little friction to finding that starting point. For reference, here's what the Explorer portion on our implementation looks like.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2y50grwgdnhzdn5cegl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2y50grwgdnhzdn5cegl.png" alt="explore.opensauced.pizza screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before I forget to explain this part, the flow state came from the fun challenge of chopping up OneGraph's GraphQL schema, on the client side. I searched around, and I really couldn't find any practical examples of this.  So now I got to venture into data science-y territory of manipulating a dataset iteratively :-) &lt;/p&gt;

&lt;p&gt;When you look at a GraphQL result of an introspection query (where a GraphQL endpoint describes itself), it's mainly a long flat list of "types". These types refer to each other in different ways, and the GraphiQL tool uses all of this data to build up a dynamic UI to work with valid GraphQL queries. Also, a GraphQL schema gets validated in handling all of the cross references and such. In order to get things the way we wanted it, we needed to modify the schema to only include the pieces we absolutely needed. I tried unsuccessfully to take the approach of picking the parts of the schema I wanted and followed the links outward to extrapolate the required parts. Don't remember exactly why but it DID NOT WORK. So I settled on the opposite - tear out the parts I didn't want and work with whatever was left. This explains the wicked long regex I used!&lt;/p&gt;

&lt;p&gt;Normally, the way GraphiQL React components would work with the schema would be something like this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;buildClientSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But instead, the way the changes read:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// To modify schema, we follow this process:&lt;/span&gt;
&lt;span class="c1"&gt;// 1) Remove all the types we don't want, based on regex match&lt;/span&gt;
&lt;span class="c1"&gt;// 2) Strip out all of the dependencies that matched the same regex&lt;/span&gt;
&lt;span class="c1"&gt;// 3) Remove types of kind=OBJECT that have had their fields emptied out (to satisfy schema validation)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredTypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;types&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nodeBlackListFn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stripPrefixedDeps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;emptyObjectFilterFn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;__schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__schema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;filteredTypes&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;buildClientSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filteredData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now utility functions that make this work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blacklistRe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;adroll|airtable|apollo|asana|box|brex|bundlephobia|chargebee|clearbit|cloudflare|contentful|crunchbase|descuri|devTo|dribbble|dropbox|eggheadio|emailNode|eventil|facebookBusiness|fedex|firebase|google|googleAds|hubspot|immigrationGraph|intercom|logdna|mailchimp|meetup|mixpanel|mux|netlify|notion|npm|openCollective|orbit|productHunt|quickbooks|rss|salesforce|slack|spotify|stripe|trello|twilio|twitchTv|twitter|ups|usps|ynab|youTube|youTubeSearch|youTubeVideo|zeit|zendesk&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;typeBlackListFn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;blacklistRe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;blacklistRe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ofType&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ofType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;blacklistRe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ofType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Filter function for picking things that are not blacklisted&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nodeBlackListFn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;blacklistRe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;blacklistRe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Strips out dependencies that are blacklisted&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stripPrefixedDeps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;typeBlackListFn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;inputFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputFields&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputFields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;typeBlackListFn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inputFields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;possibleTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;possibleTypes&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;possibleTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;typeBlackListFn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;possibleTypes&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;// Removes OBJECT types that have had all of their fields stripped out.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emptyObjectFilterFn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OBJECT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There was one other feature in the same PR, that I'll talk about next week!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>graphql</category>
      <category>opensource</category>
      <category>node</category>
    </item>
  </channel>
</rss>
