<?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: Rubén Sospedra</title>
    <description>The latest articles on DEV Community by Rubén Sospedra (@sospedra).</description>
    <link>https://dev.to/sospedra</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%2F51982%2F7a168b13-7019-49e7-9759-c6392b00bcbf.jpeg</url>
      <title>DEV Community: Rubén Sospedra</title>
      <link>https://dev.to/sospedra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sospedra"/>
    <language>en</language>
    <item>
      <title>On TypeScript unions</title>
      <dc:creator>Rubén Sospedra</dc:creator>
      <pubDate>Fri, 26 Feb 2021 08:52:14 +0000</pubDate>
      <link>https://dev.to/sospedra/on-typescript-unions-p5n</link>
      <guid>https://dev.to/sospedra/on-typescript-unions-p5n</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://sospedra.me/papers/typescript-unions"&gt;Original content&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Not a single day passes without finding a multi-type TypeScript entity that messes your code. Successful API responses can adopt multiple shapes. Collections may contain many types within them. Parsed user inputs can collapse to different scalars. It's expected. That's why TypeScript supports Unions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;idk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Potato&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Being able to define any entity with precision is great. But that's only half of the solution. Once we have a &lt;a href="https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html"&gt;Union&lt;/a&gt; type in our hands we may want to conditionally act on it. Depending on what type matches the value at each moment. That's a fancy way to define a bunch of if-else. And, indeed, in most cases TypeScript is smart enough to infer the right type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;idk&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&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="c1"&gt;// idk: String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// idk: number | Potato&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This process is call &lt;a href="https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions"&gt;Discrimination&lt;/a&gt;. It's the other half of the solution. With simple entities such as the one below it's pretty straightforward. However, discriminating against objects can be tough.&lt;br&gt;
The good thing is that TypeScript is smart enough to identify when there's a discrimination problem. More often than not I stumble upon it:&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;Property&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;does&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;exist&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A&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;B&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Identifier keys
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://github.com/Microsoft/TypeScript/pull/9163"&gt;recommended way&lt;/a&gt; to do it is by having a &lt;strong&gt;constant string-type field in the object&lt;/strong&gt;. For TypeScript will infer the type using that field as an anchor. The same way it does with primitive types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;VaporCoin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vapor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NeonCoin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;neon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;act&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;coin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VaporCoin&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;NeonCoin&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;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;coin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vapor&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="c1"&gt;// coin: VaporCoin&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;neon&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="c1"&gt;// coin: NeonCoin&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;h3&gt;
  
  
  Morphic check
&lt;/h3&gt;

&lt;p&gt;But, sometimes it's not possible to rely upon one specific field. Maybe it's not even up to us to decide the object shapes - working with a third-party API. In such cases, we can &lt;strong&gt;infer the type by running a morphic check&lt;/strong&gt;. Meaning, looking for differences in their shape.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;VaporCoin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;vapor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NeonCoin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;neon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;act&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;coin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VaporCoin&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;NeonCoin&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vapor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;coin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// coin: VaporCoin&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// coin: NeonCoin&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;h3&gt;
  
  
  TBD functions
&lt;/h3&gt;

&lt;p&gt;Finally, when everything else failed. We can &lt;strong&gt;use a to-be-defined function&lt;/strong&gt;. If the objects don't have an identifier field. If they are morphally equal. We can check their inner differences with a function. And let this TBD function to imperatively coerce the type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;VaporCoin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;NeonCoin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isVapor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tbd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;tbd&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;VaporCoin&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;tbd&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;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vapor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;act&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;coin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;VaporCoin&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;NeonCoin&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isVapor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;coin&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// coin: VaporCoin&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// coin: NeonCoin&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;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Unions and Intersections are part of TypeScript's backbone. These are powerful and we must embrace their usage as much as possible. Once we start working with them we must learn how to discriminate different types. For that I recommend that everyone &lt;strong&gt;follows this step-through&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;By default, &lt;strong&gt;let TypeScript's inference do its magic&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Any normal &lt;strong&gt;if-else&lt;/strong&gt; will suffice &lt;strong&gt;for simple types&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;When discriminating objects use &lt;strong&gt;identifier fields&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If that's not possible, use &lt;strong&gt;morphic checks&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;As a last resource, use &lt;strong&gt;TBD functions&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>architecture</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>GitHub as a Service</title>
      <dc:creator>Rubén Sospedra</dc:creator>
      <pubDate>Wed, 20 May 2020 14:22:17 +0000</pubDate>
      <link>https://dev.to/sospedra/github-as-a-service-e38</link>
      <guid>https://dev.to/sospedra/github-as-a-service-e38</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was originally posted with code examples at &lt;a href="https://www.sospedra.me/papers/gaas"&gt;sospedra.me/papers/gaas&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the past years, GitHub became a technology mastodon. Since the &lt;a href="https://news.microsoft.com/2018/06/04/microsoft-to-acquire-github-for-7-5-billion/"&gt;acquisition by Microsoft&lt;/a&gt;, the company added a myriad of outstanding features. &lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt;, in-house CI/CD, a marketplace, the &lt;a href="https://github.blog/2020-03-16-npm-is-joining-github/"&gt;integration of npm&lt;/a&gt;, et al. In fact, &lt;strong&gt;GitHub is so powerful nowadays that it can be your all-in-all provider&lt;/strong&gt;. You can use &lt;strong&gt;GitHub as a Service&lt;/strong&gt;. GaaS, Gaas, Gaas!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is GaaS?
&lt;/h2&gt;

&lt;p&gt;GitHub's variety of products is extensive enough to power most of the web apps out there. Don't believe me? Let's go through my journey building &lt;a href="https://rfm.sospedra.me/"&gt;Request For Maintainers&lt;/a&gt; (RFM).&lt;/p&gt;

&lt;p&gt;This project is a community-driven platform to track any repository calling for support. From the product point of view, I want to help the community to have a clean record of the OSS status. On the tech side, this project is an experiment I got in my mind for so long. &lt;strong&gt;RFM runs 100% on GitHub services&lt;/strong&gt;. And it's &lt;a href="https://github.com/sospedra/rfm"&gt;open-sourced&lt;/a&gt; so anyone is welcome to check the nuts and bolts.&lt;/p&gt;

&lt;p&gt;If you want to build a web app that runs on GitHub you're gonna need some foundations. Basic things that are common to any web. But, before getting started, a disclaimer. I didn't read the terms and conditions and all the legal dullness. But I can sense this approach &lt;del&gt;maybe&lt;/del&gt; exceeds the intended purposes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hosting&lt;/strong&gt;: for what &lt;strong&gt;GitHub repositories&lt;/strong&gt; excel. But wait, there's more! &lt;a href="https://pages.github.com/"&gt;GitHub pages&lt;/a&gt; put your web under a CDN, with SSL certs, and all the other goodies you'll expect from your trusted provider.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Database&lt;/strong&gt;: if you don't have anything to hide 🌝 then &lt;strong&gt;GitHub Issues is a wonderful database&lt;/strong&gt;. For example, you can store a stringified JSON in the body. Or benefit from the Issue metadata.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server&lt;/strong&gt;: most of the heavy lifting will happen in the client. But sometimes you need some special functions to run on the cloud. Did anyone say &lt;strong&gt;serverless&lt;/strong&gt;? 💊&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Auth&lt;/strong&gt;: Do you need to put some access restrictions? Well, GitHub has a top-notch &lt;a href="https://developer.github.com/apps/building-oauth-apps/"&gt;OAuth service&lt;/a&gt; implemented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Secrets&lt;/strong&gt;: Another interesting side-effect is the &lt;strong&gt;env secrets management&lt;/strong&gt;. Since GitHub repositories already have a secret values system. We can use that to run out GitHub Actions as serverless functions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Read the same post with code snippets in the &lt;a href="https://www.sospedra.me/papers/gaas"&gt;original post&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At this point, I guess you get the idea. But how we put together all the pieces? Let's see how I built RFM step by step. You'll see it's not that complex at all.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You need your web to be &lt;strong&gt;statically generated&lt;/strong&gt;. There are tones of options: &lt;code&gt;Jekyll&lt;/code&gt;, &lt;code&gt;create-react-app&lt;/code&gt;, an old-fashion raw &lt;code&gt;HTML&lt;/code&gt;. Whatever. The important bit is that to use GitHub pages it must be &lt;strong&gt;static&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You consume your fancy database with the public &lt;a href="https://developer.github.com/v3/"&gt;GitHub API&lt;/a&gt;. The public part is a no key-required standard CRUD. Your web app will &lt;strong&gt;use this API to get GitHub Issues&lt;/strong&gt;. You can tweak your query with multiple params: the state, labels, content, assignation, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When in need of &lt;strong&gt;server functions use GitHub Actions&lt;/strong&gt;. These deliver an outstanding experience. They are so powerful. The basic idea is that a custom trigger will execute a custom function. There's a &lt;a href="https://github.com/marketplace"&gt;marketplace&lt;/a&gt; you can explore or &lt;a href="https://help.github.com/en/actions/building-actions"&gt;you can build your own&lt;/a&gt;. It's free real state!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To integrate RFM with GitHub I use the &lt;a href="https://help.github.com/en/github/managing-your-work-on-github/about-automation-for-issues-and-pull-requests-with-query-parameters"&gt;GitHub Query Parameters&lt;/a&gt;. You know, remember to avoid &lt;em&gt;Hooman Paws&lt;/em&gt;™️ as much as possible. There's a well-known library that can do the heavy parsing for us: &lt;a href="https://github.com/sindresorhus/new-github-issue-url"&gt;new-github-issue-url&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, tweak the limitations. You can either add some auth with the GitHub OAuth. Or play with the Issues metadata, Actions triggers, etc. In RFM the actions are &lt;strong&gt;executed only when the issue has a particular label&lt;/strong&gt;. Only moderators can assign labels. That's the way I avoid RFM being a spammy tool.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Am I suggesting that y'all should use &lt;strong&gt;GaaS&lt;/strong&gt; from now on? Well, absolutely no 🤷🏻‍♂️. But, there are some cases where this can be beneficial. I'm thinking of OSS projects, mostly. In fact, using &lt;a href="https://utteranc.es/"&gt;GitHub Issues as blog post comments&lt;/a&gt; it's being a common practice for a long time. This is an evolution of the same concept. The actual point is: &lt;strong&gt;GitHub becomes an infra beast&lt;/strong&gt; lately. We should keep an eye here and consider pushing the limits as much as possible.&lt;/p&gt;

</description>
      <category>github</category>
      <category>saas</category>
      <category>serverless</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
