<?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: Valentin Degenne</title>
    <description>The latest articles on DEV Community by Valentin Degenne (@vdegenne).</description>
    <link>https://dev.to/vdegenne</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%2F380388%2F49efdc15-d273-4fe4-be1d-0ad2e2b3dbc3.jpeg</url>
      <title>DEV Community: Valentin Degenne</title>
      <link>https://dev.to/vdegenne</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vdegenne"/>
    <language>en</language>
    <item>
      <title>Rollup/Vite Plugin hooks comparison</title>
      <dc:creator>Valentin Degenne</dc:creator>
      <pubDate>Mon, 15 Jan 2024 12:27:23 +0000</pubDate>
      <link>https://dev.to/vdegenne/rollupvite-hooks-comparison-oma</link>
      <guid>https://dev.to/vdegenne/rollupvite-hooks-comparison-oma</guid>
      <description>&lt;p&gt;Let's be honest making plugins in Rollup can be exhausting, making plugins in Vite can be exhausting, but trying to develop a utility that supports both version, with same inputs expecting the same output is where the real adventure begins.&lt;br&gt;&lt;br&gt;
Here's a small analysis and comparison that can help thinking things through.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rollup
&lt;/h2&gt;

&lt;p&gt;First let's run this snippet,&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;buildStart&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;build started&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="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`transforming &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&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="nf"&gt;buildEnd&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;build ended&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;If we run &lt;code&gt;npx rollup -c&lt;/code&gt;, here's the output&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

build started
transforming src/index.js
build ended


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

&lt;/div&gt;

&lt;p&gt;Nothing surprising, now if we run &lt;code&gt;npx rollup -cw&lt;/code&gt; (watch), we got&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

build started
transforming src/index.js
build ended


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

&lt;/div&gt;

&lt;p&gt;Same output but now it's waiting for changes. What happens if we change &lt;code&gt;index.js&lt;/code&gt;? Then the output will be the same, &lt;code&gt;buildStart&lt;/code&gt; and &lt;code&gt;buildEnd&lt;/code&gt; hooks are always called, and &lt;code&gt;transform&lt;/code&gt; is subsequently called on changed files only (there is a cache system).&lt;/p&gt;

&lt;p&gt;Let's jump on Vite behavior before we can compare the two.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vite
&lt;/h2&gt;

&lt;p&gt;Here's our test config&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&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="nf"&gt;buildStart&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;build started&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="nf"&gt;transformIndexHtml&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transform index html&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="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`transforming &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&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="nf"&gt;buildEnd&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;build ended&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;And let's run &lt;code&gt;npx vite build&lt;/code&gt;, here's the output:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

build started
transforming src/index.js
build ended
transform index html


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

&lt;/div&gt;

&lt;p&gt;Very similar to Rollup. In Vite &lt;code&gt;transformIndexHtml&lt;/code&gt; can be used to transform the final index html.&lt;br&gt;&lt;br&gt;
Now let see when we run Vite in watch mode (dev) using &lt;code&gt;npx vite&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

build started
transform index html
transforming src/index.js


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

&lt;/div&gt;

&lt;p&gt;Ok what's going on here? Why is the index html transformed before the script and where is &lt;code&gt;build ended&lt;/code&gt; log? The index is prior to the script because it's the first resource dynamically called during development. For the &lt;code&gt;buildEnd&lt;/code&gt; hook, well... dev is not build so it makes sense (who is using this hook anyway?)&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison
&lt;/h2&gt;

&lt;p&gt;Now that we have enough understanding of how both systems work, it's time to make a cheat sheet for a quick comparison:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fog3ocak9axk06mqixrim.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%2Fog3ocak9axk06mqixrim.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first thing to notice is that both Rollup and Vite have pretty similar execution for the build process. Things get tricky in watch mode.&lt;/p&gt;

&lt;p&gt;Another thing important to note is that &lt;code&gt;buildStart&lt;/code&gt; and &lt;code&gt;transformIndexHtml&lt;/code&gt; can be asynchronous which means the content transformations won't actually start until these functions are actually resolved.&lt;/p&gt;

</description>
      <category>rollup</category>
      <category>vite</category>
      <category>plugin</category>
      <category>node</category>
    </item>
    <item>
      <title>Few things about page loading and styling.</title>
      <dc:creator>Valentin Degenne</dc:creator>
      <pubDate>Thu, 28 Dec 2023 09:36:05 +0000</pubDate>
      <link>https://dev.to/vdegenne/few-things-about-page-loading-and-styling-2gka</link>
      <guid>https://dev.to/vdegenne/few-things-about-page-loading-and-styling-2gka</guid>
      <description>&lt;p&gt;One thing to keep in mind when designing a website is that the browser can fetch several resources when the page loads but has a limitation on how many it can download at a time.&lt;br&gt;
So one must be wise and put all the necessary things at the beginning: code splitting can help with that.&lt;br&gt;
But it's a double edged sword problem, split enough to make things load in parallel and speed up the &lt;a href="https://web.dev/articles/lcp"&gt;lcp&lt;/a&gt; but do not split too much because it could defer the loading of some needed scripts.&lt;/p&gt;
&lt;h2&gt;
  
  
  StyleSheets
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Applying a style from a script...
&lt;/h3&gt;

&lt;p&gt;One solution to reduce the number of requests sent to your server is to slide your stylesheets directly inside your scripts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;neededStyles&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;./need-styles.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="kd"&gt;with&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;css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;adoptedStyleSheets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;neededStyles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A document or shadow root can have as many stylesheets as supported and stylesheets stack on top of each other (assuming &lt;code&gt;push&lt;/code&gt; is being used). Adding a new stylesheet doesn't discard the previously added ones &lt;em&gt;but will replace the css properties in common&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  modulepreload
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fetch scripts before they are even requested in others, that can speed up the load time (compared to requesting them in cascade over the network at execution time).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;However&lt;/strong&gt; preloading a module doesn't execute the script*!* (it just preloads its content).&lt;/li&gt;
&lt;li&gt;Preloading a module won't cause a preloading cascade, every scripts need to explicitely be preloaded even the ones included inside a preloaded script:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;main.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./sub.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;index.html&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"modulepreload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"./main.js"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- The following preload is also needed
     even though `sub.js` is imported from `main.js` --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"modulepreload"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"./sub.js"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Firestore</title>
      <dc:creator>Valentin Degenne</dc:creator>
      <pubDate>Sun, 18 Jun 2023 18:32:58 +0000</pubDate>
      <link>https://dev.to/vdegenne/firestore-37jo</link>
      <guid>https://dev.to/vdegenne/firestore-37jo</guid>
      <description>&lt;h1&gt;
  
  
  Firestore rules
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;If no rules are applied to a resource, no one can read/write in it.&lt;/li&gt;
&lt;li&gt;Rules are applied to &lt;em&gt;and only&lt;/em&gt; to the specified matched pattern and are not recursive. For instance allowing read access on &lt;code&gt;/users/{uid}&lt;/code&gt; won't allow read access on &lt;code&gt;/users/{uid}/documents/{docId}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Only 1MB of data per document allowed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Accept access for everyone
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;match /path/to/resource {
  allow read: if true;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Accept access if the user is connected
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;match /path/to/resource {
  allow read: if request.auth != null;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Make a resource user-specific
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;match /user/{uid}/path/to/resource {
  allow read: if request.auth.uid == uid;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;!! Important !!&lt;/strong&gt; A path to a resource is a path to a document, for instance read access on &lt;code&gt;"/users/{uid}/records"&lt;/code&gt; is not going to make a user able to read documents in that collection, the correct path would be &lt;code&gt;"/users/{uid}/records/{recordId}"&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Defining a function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function isAllowed(userId) {
  return request.auth.uid == userId;
}
match /user/{userId}/path/to/resource {
  allow read, write: if isAllowed(userId);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  JavaScript Web Modular SDK
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;addDoc&lt;/code&gt;: takes a collection and add the provided data, a document is appended to the collection with an auto-generated id. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setDoc&lt;/code&gt;: takes a document path (with custom id) and insert data, creates the document if it doesn't exist, if the document already exists the document is replaced (&lt;strong&gt;everything&lt;/strong&gt; is replaced by the new data and data might be lost unless &lt;code&gt;{ merge: true }&lt;/code&gt; is used).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;updateDoc&lt;/code&gt;: takes an existing document path (with custom id) and merge data, but if the document doesn't exist, the call throws an error.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  onSnapshot
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Can listen both on a document or a collection.&lt;/li&gt;
&lt;li&gt;Callback on a document is called when information in the document changes &lt;strong&gt;but not if a collection is created/updated/removed inside of it&lt;/strong&gt; (in fact a collection does not directly belong to a document.)&lt;/li&gt;
&lt;li&gt;Callback on a collection is called when documents are added/updated/removed inside this collection &lt;strong&gt;but not if a collection is created/updated/removed inside one of the documents&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  arrayUnion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Doesn't work with &lt;code&gt;setDoc&lt;/code&gt; and will replace all values.&lt;/li&gt;
&lt;li&gt;Should be used with &lt;code&gt;updateDoc&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Installing Stripe in Firebase manually.</title>
      <dc:creator>Valentin Degenne</dc:creator>
      <pubDate>Thu, 15 Jun 2023 10:12:42 +0000</pubDate>
      <link>https://dev.to/vdegenne/installing-stripe-in-firebase-manually-1f18</link>
      <guid>https://dev.to/vdegenne/installing-stripe-in-firebase-manually-1f18</guid>
      <description>&lt;p&gt;There is an easy way to install Stripe into Firebase using the extension available from the &lt;a href="https://extensions.dev/extensions/stripe/firestore-stripe-payments"&gt;extensions hub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So why going into much trouble and do it manually? Here's the reasons why I thought I'd make a tutorial for it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consolidating Firebase functions knowledge in general.&lt;/li&gt;
&lt;li&gt;Having a better understanding of how Stripe and Firebase interact with each other.&lt;/li&gt;
&lt;li&gt;Proving that it's in fact possible to do it manually and everything is clear and transparent to us.&lt;/li&gt;
&lt;li&gt;Being able to customize the "build" and having more control if we want to implement more logic in functions.&lt;/li&gt;
&lt;li&gt;Being able to use Stripe locally and use it with the Emulator suite.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get straight to the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparation
&lt;/h2&gt;

&lt;p&gt;Before trying to install anything, make sure you have already done the following.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a Firebase account, creating a project inside and upgrading the project to a Blaze plan of course&lt;sup&gt;1&lt;/sup&gt;
&lt;/li&gt;
&lt;li&gt;Activating both Firestore and Authentication in the Firebase console of that project.&lt;/li&gt;
&lt;li&gt;Installing &lt;a href="https://nodejs.org/en"&gt;NodeJs&lt;/a&gt; (+npm)&lt;/li&gt;
&lt;li&gt;Installing &lt;a href="https://git-scm.com/downloads"&gt;git&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Installing &lt;code&gt;firebase&lt;/code&gt; command line tool (&lt;code&gt;npm i -g firebase-tools&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ok let's jump right in&lt;/p&gt;

&lt;h1&gt;
  
  
  0. Requirements
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This tutorial assumes you already have an existing local development directory of the project where you want to install Stripe functionalities on your machine.&lt;br&gt;&lt;br&gt;
If that's not the case, please create a directory and initialize a Firebase project. For instance&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;myProject
&lt;span class="nb"&gt;cd &lt;/span&gt;myProject
firebase init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During the &lt;code&gt;init&lt;/code&gt; process make sure to install &lt;em&gt;Firestore&lt;/em&gt; and &lt;em&gt;Functions&lt;/em&gt; (and Emulators if you need them). The values you enter there are up to you and will not conflict with any of the steps further in this tutorial. It's important that a &lt;code&gt;functions&lt;/code&gt; directory exists at the root of your project before continuing.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Cloning base files
&lt;/h1&gt;

&lt;p&gt;Clone the following repository &lt;strong&gt;inside you project directory&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/vdegenne/install-firebase-stripe-manually.git stripe-functions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  2. Inform the CLI of the new functions source (codebase)
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to follow these values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;select "Functions" feature using spacebar then Enter&lt;/li&gt;
&lt;li&gt;select "Initialize"&lt;/li&gt;
&lt;li&gt;choose a name for the codebase (e.g. "stripe-functions")&lt;/li&gt;
&lt;li&gt;choose "stripe-functions" for the sub-directory name.&lt;/li&gt;
&lt;li&gt;select "TypeScript"&lt;/li&gt;
&lt;li&gt;use ESLint if you want&lt;/li&gt;
&lt;li&gt;Press Enter to choose the default "No" to every "Overwrite?" notices.&lt;/li&gt;
&lt;li&gt;Finally choose "Yes" to install the dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point in time you should have two codebases installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;functions&lt;/code&gt;: the main functions of your app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;stripe-functions&lt;/code&gt;: the functions relative to Stripe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;(You can see details in &lt;code&gt;firebase.json&lt;/code&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Build the sources
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;stripe-functions
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Builds are in the &lt;code&gt;lib&lt;/code&gt; directory in CommonJS format, those are the files Firebase will use during the deployment phase.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At this moment of the tutorial, if you try to deploy the functions then the CLI &lt;/p&gt;

&lt;p&gt;// ------------- START DEPRECATED -----------------&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Build sources
&lt;/h1&gt;

&lt;p&gt;From here we should take few minutes to think how to integrate the functions, there are few possible solutions:&lt;/p&gt;

&lt;h3&gt;
  
  
  a. I don't need to emulate Stripe during development
&lt;/h3&gt;

&lt;p&gt;If the end goal is to just install stripe functions in GC and we don't need to use it with the emulator, then it's pretty straightforward, just run &lt;code&gt;npm run build&lt;/code&gt; and jump right to the next chapter.&lt;/p&gt;

&lt;h3&gt;
  
  
  b. I need to emulate and I don't have existing functions
&lt;/h3&gt;

&lt;p&gt;This case is also easy to cover, just create a directory called &lt;code&gt;functions&lt;/code&gt; at the root of your project and copy all the content of the cloned repository inside this freshly created directory. Then&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;functions
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And jump to the next chapter.&lt;/p&gt;

&lt;h3&gt;
  
  
  c. I need to emulate and I have existing functions
&lt;/h3&gt;

&lt;p&gt;To avoid conflicts with your existing files rename &lt;code&gt;src/index.ts&lt;/code&gt; to a name of your choice (e.g. &lt;code&gt;stripe.ts&lt;/code&gt;) and any other filenames that may conflict with yours.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you don't use TS&lt;/strong&gt; then build the sources (&lt;code&gt;npm run build&lt;/code&gt;) and copy all content from &lt;code&gt;/lib&lt;/code&gt; to your existing &lt;code&gt;functions&lt;/code&gt; directory (the files are in CommonJS format, if you are using ESM then you'll have to find a way to compile them).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are already using TS&lt;/strong&gt; then copy all the files from &lt;code&gt;src&lt;/code&gt; to your existing functions directory. Make sure to install the dependencies needed by these files (take &lt;code&gt;package.json&lt;/code&gt; as a reference, the files need specific versions) and then build and jump to the next chapter.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(In both cases above don't forget to import/export all the components coming from the stripe index file into your main index file)&lt;/em&gt;&lt;br&gt;
// ------------- END DEPRECATED -----------------&lt;/p&gt;

&lt;h2&gt;
  
  
  - Initializing the project in a directory (&lt;code&gt;firebase init&lt;/code&gt;) + installing the functions emulator during that same process.
&lt;/h2&gt;




&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; The Blaze Plan is what will unlock the "functions" feature in Firabase.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(here's the &lt;a href="https://github.com/vdegenne/install-firebase-stripe-manually"&gt;link to github repository&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Firebase functions "in short"</title>
      <dc:creator>Valentin Degenne</dc:creator>
      <pubDate>Wed, 14 Jun 2023 11:17:31 +0000</pubDate>
      <link>https://dev.to/vdegenne/firebase-functions-in-short-1i59</link>
      <guid>https://dev.to/vdegenne/firebase-functions-in-short-1i59</guid>
      <description>&lt;p&gt;Firebase functions let you write the logic of your application on the servers of Google.&lt;/p&gt;

&lt;p&gt;A function is like a callback that gets executed whenever &lt;em&gt;something happens&lt;/em&gt; in your application, i.e. when a user is created/deleted, when your Firestore database changes, etc...&lt;/p&gt;

&lt;p&gt;You can then execute anything that you want on these special events. &lt;/p&gt;

&lt;h2&gt;
  
  
  Source of truth
&lt;/h2&gt;

&lt;p&gt;All the development you are doing on your local machine is considered source of truth. That means every time you need to augment the functionality of your application you have to develop your functions locally and push/deploy them on the cloud.&lt;br&gt;
But the contrary is not true, for instance if you delete a function directly from the console there is no way to reflect the change locally. &lt;/p&gt;
&lt;h2&gt;
  
  
  Blaze Plan
&lt;/h2&gt;

&lt;p&gt;If you want to use cloud functions you will need to upgrade your project to a Firebase &lt;em&gt;Blaze Plan&lt;/em&gt; (&lt;a href="https://firebase.google.com/pricing"&gt;more details here&lt;/a&gt;).&lt;br&gt;
Don't worry you don't have to pay to switch to that plan because Spark plan is included (but I would still recommend you set a billing alert.)&lt;/p&gt;
&lt;h2&gt;
  
  
  Google Cloud
&lt;/h2&gt;

&lt;p&gt;Behind the scene Firebase is just a candy-wrapped and user-friendly platform for introducing new users to the Google Cloud world. For instance when you create a Firebase function, in reality the function is just installed on Google Cloud servers.&lt;br&gt;
You can check installed functions and their details at any time going to the &lt;a href="https://console.cloud.google.com/functions/list"&gt;cloud functions page&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Config
&lt;/h2&gt;

&lt;p&gt;Configs let you pass environmental variables in your functions at runtime. There are few ways of doing that:&lt;/p&gt;
&lt;h3&gt;
  
  
  functions.config
&lt;/h3&gt;

&lt;p&gt;This is considered the old way, you can use the following command to register a runtime value&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;firebase functions:config:set MY_KEY="something"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(note: This will save the value in the cloud directly and they will be included inside each deployed functions)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;firebase functions:config:get &amp;gt; .runtimeconfig.json&lt;/code&gt; to save the config object inside &lt;code&gt;functions&lt;/code&gt; directory, and then you can retrieve values in your functions with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-functions/v1&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;MY_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;But if your function is defined as a v2 function you should use v2 accessories&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  v2
&lt;/h3&gt;

&lt;p&gt;In Firebase v2 you have 3 options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Parameterized configuration&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;defineString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defineInt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-functions/params&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;myParam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defineString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MY_PARAM&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;myParam&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During emulation/deployment you'll be asked to enter a default value for your params, and a &lt;code&gt;.env.&amp;lt;project_id&amp;gt;&lt;/code&gt; file will be created inside the &lt;code&gt;functions&lt;/code&gt; directory (&lt;a href="https://firebase.google.com/docs/functions/config-env?gen=2nd#params"&gt;more info there&lt;/a&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;dotenv&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To use this configuration pattern, create &lt;code&gt;.env&lt;/code&gt; file in the &lt;code&gt;functions&lt;/code&gt; directory.&lt;br&gt;
Then you can access them in your functions using &lt;code&gt;process.env.&amp;lt;VAR&amp;gt;&lt;/code&gt;.&lt;br&gt;
you can have different &lt;code&gt;.env.&amp;lt;type&amp;gt;&lt;/code&gt; file and use &lt;code&gt;firebase use&lt;/code&gt; to use one or another (&lt;a href="https://firebase.google.com/docs/functions/config-env?gen=2nd#env-variables"&gt;more details there&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;If you need to migrate from v1 to dotenv, you can use this command &lt;code&gt;firebase functions:config:export&lt;/code&gt;. That will export the config values in appropriate dot env files.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;secrets&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is considered most secured and also convenient (but with convenience comes a cost?).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://firebase.google.com/docs/functions/config-env?gen=2nd#create-secret"&gt;More details here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(&lt;a href="https://github.com/stripe/stripe-firebase-extensions/tree/master/firestore-stripe-payments"&gt;firestore-stripe-payments&lt;/a&gt; create a GC secret during the installation)&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;For more details about config please &lt;a href="https://firebase.google.com/docs/functions/config-env?gen=2nd"&gt;read this&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be aware&lt;/strong&gt;: &lt;a href="https://github.com/firebase/firebase-functions/issues/1094#issuecomment-1595351596"&gt;environment variables are not being loaded during deployment&lt;/a&gt;&lt;br&gt;
Here's a possible solution&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;config&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;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// now process.env.&amp;lt;VARNAME&amp;gt; will be available&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(note that &lt;code&gt;config()&lt;/code&gt; only interprets values in &lt;code&gt;.env&lt;/code&gt; by default)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Emulator
&lt;/h2&gt;

&lt;p&gt;We can use &lt;code&gt;firebase&lt;/code&gt; command tool to try out our functions before deployment using the emulator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;firebase emulators:start --only functions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deploying
&lt;/h2&gt;

&lt;p&gt;Once you are done with the development phase, you can deploy your functions using&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;firebase deploy --only functions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Firebase will create an endpoint for all the exposed functions.&lt;/p&gt;

&lt;p&gt;During deployment the JavaScript files are being packaged and sent to the cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Codebases
&lt;/h2&gt;

&lt;p&gt;You can have different functions &lt;a href="https://firebase.google.com/docs/functions/organize-functions?gen=2nd"&gt;codebases&lt;/a&gt; within your project. This allows you to organize functions into different directories/environments.&lt;br&gt;&lt;br&gt;
It can also help for the deployment as you are able to filter and deploy only functions from a specified codebase, e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase deploy &lt;span class="nt"&gt;--only&lt;/span&gt; functions:&amp;lt;codebase_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create a new codebase just run &lt;code&gt;firebase init&lt;/code&gt; and select "Functions" and follow the prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logger
&lt;/h2&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;logger&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;firebase-functions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use the logger from gcloud package (TODO)&lt;/p&gt;

&lt;h2&gt;
  
  
  Miscellaneous information
&lt;/h2&gt;

&lt;p&gt;You can code split functions into various files as far as you import-export them inside the &lt;code&gt;index.js&lt;/code&gt; file (which is the entry point defined in package.json)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[ Article in Progress ]&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My journey as I try to install Stripe in my app.</title>
      <dc:creator>Valentin Degenne</dc:creator>
      <pubDate>Wed, 14 Jun 2023 09:38:30 +0000</pubDate>
      <link>https://dev.to/vdegenne/my-journey-as-i-try-to-install-stripe-in-my-app-1boa</link>
      <guid>https://dev.to/vdegenne/my-journey-as-i-try-to-install-stripe-in-my-app-1boa</guid>
      <description>&lt;p&gt;&lt;a href="https://stripe.com/en-fr"&gt;Stripe&lt;/a&gt; is at core a REST API (somewhere) that you can use to manage a payment system for your application.&lt;/p&gt;

&lt;p&gt;Fortunately, if you already use Firebase, the process of installing Stripe is extremely simplified, but it doesn't mean that it is just few buttons to push.&lt;/p&gt;

&lt;p&gt;Here's a succinct list of all the steps:&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Stripe account.
&lt;/h2&gt;

&lt;p&gt;Creating a stripe account is easy. By default Stripe comes with a testing environment (test key, ...). That means you don't need to provide your banking informations until you bring your app to production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the Stripe extension into Firebase
&lt;/h2&gt;

&lt;p&gt;Before installing the extension, you'll need to do few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure to upgrade your project to &lt;em&gt;Blaze Plan&lt;/em&gt;. Upgrading your account is necessary because the extension installs some "functions" which is how Firebase and Stripe services communicate together on special events.&lt;/li&gt;
&lt;li&gt;Install Firestore and Authentication Firebase services before continuing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once that's done, you can install the &lt;code&gt;firestore-stripe-payments&lt;/code&gt; extension from the &lt;a href="https://extensions.dev/extensions/stripe/firestore-stripe-payments"&gt;extensions hub&lt;/a&gt; or directly from Firebase "extensions" section.&lt;/p&gt;

&lt;p&gt;The installation takes few minutes.&lt;br&gt;
And when it finishes successfully, you are ready to go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;However for me that's where things started to be confusing.&lt;/strong&gt; And that's where we should start to ask the right questions:&lt;/p&gt;

&lt;h3&gt;
  
  
  - What does the extension install exactly?
&lt;/h3&gt;

&lt;p&gt;Primarily the extension installs a bunch of functions. (If you are not familiar with functions and what they do please &lt;a href="https://firebase.google.com/docs/functions"&gt;read this&lt;/a&gt;). Basically functions are like callbacks that are executed on special events (when a user is created/deleted, when a document is pushed inside a path in Firestore, etc...).&lt;/p&gt;

&lt;p&gt;You can check all the installed functions inside your project going to the functions page in Firebase console:&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;(note: you can always see more details about functions going to the &lt;a href="https://console.cloud.google.com/functions/list"&gt;Cloud functions dedicated page&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first function of interest is the first one. Basically Stripe API creates a checkout session when you push a checkout session document inside the &lt;code&gt;checkout_sessions&lt;/code&gt; collection associated with a user. In turn Firebase will update this document with a session ID returned by Stripe API. You can then use this session ID to redirect the user on a Stripe customized checkout page providing this id.&lt;/p&gt;

&lt;h3&gt;
  
  
  - Is it possible to see the implementation of the functions?
&lt;/h3&gt;

&lt;p&gt;Not directly inside Firebase, but here's the &lt;a href="https://github.com/stripe/stripe-firebase-extensions/tree/master/firestore-stripe-payments"&gt;source page&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Things that Stripe extension modifies in the cloud
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add a "Firebase Extensions firestore-stripe-payments service account"&lt;/li&gt;
&lt;li&gt;Add the Stripe API key in Google Cloud Secret Manager. This key is used for Firebase functions to securely communicate with the Stripe API.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Article still in progress.....
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>My journey as I learn Firebase</title>
      <dc:creator>Valentin Degenne</dc:creator>
      <pubDate>Fri, 09 Jun 2023 14:21:16 +0000</pubDate>
      <link>https://dev.to/vdegenne/my-journey-as-i-learn-firebase-36je</link>
      <guid>https://dev.to/vdegenne/my-journey-as-i-learn-firebase-36je</guid>
      <description>&lt;p&gt;I've learned Firebase in the past but because I've not used it since then it was like learning it all over again, I write this post more as a reference than an actually tutorial.&lt;/p&gt;

&lt;p&gt;One thing is for sure Firebase is a bit tough to learn. It is supposed to be easy to use, but the doc is so intimidating and there are so many different concepts revolving around the platform that I found it rather exhausting to approach.&lt;/p&gt;

&lt;p&gt;I feel like the first thing most people would want to know is what is the most conventional way to &lt;em&gt;use&lt;/em&gt; it, and my answer would be: &lt;code&gt;firebase&lt;/code&gt; !&lt;/p&gt;

&lt;h2&gt;
  
  
  firebase-tools
&lt;/h2&gt;

&lt;p&gt;Do not try to configure something from the console if there is a way to configure it locally on your computer using the firebase command line tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo npm install -g firebase-tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple execution will make &lt;code&gt;firebase&lt;/code&gt; command line tool available on your system.&lt;/p&gt;

&lt;p&gt;From there you probably want to initialize a project, make sure you created the project in the console (on the website yeah) first, then in your project directory on your machine run this command (I would suggest you read all the article before running this command as it is one setup and have a lot to digest):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;firebase init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Proceed to read to have a small grasp of &lt;code&gt;firebase&lt;/code&gt; core features:&lt;/p&gt;

&lt;h2&gt;
  
  
  Authentication
&lt;/h2&gt;

&lt;p&gt;There is not much to say, that helps to create a login environment for you app. Make sure to activate this feature in the console if you need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Firestore
&lt;/h2&gt;

&lt;p&gt;This feature is like live database but more modern (?). I personally prefer using this because it can easily scale and is maybe more intuitive for new comers. You would also need to activate that in your console.&lt;/p&gt;

&lt;h2&gt;
  
  
  Functions
&lt;/h2&gt;

&lt;p&gt;An easy way to understand what functions are, is to imagine Homer Simpson behind the central console patiently waiting for any signal.&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%2Fzq5iicxq6f41d6wicyal.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%2Fzq5iicxq6f41d6wicyal.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Signals can be of all kind (e.g. "user connected", "new account created", "new data inserted inside the database (firestore)", etc...).&lt;br&gt;
When a signal is received Homer pushes a button to call the appropriate action/&lt;em&gt;function&lt;/em&gt;, now a function can be anything you define. For instance you may want to push initialization data inside firestore when a new user register on your website.&lt;br&gt;
&lt;code&gt;firebase init&lt;/code&gt; will ask you if you want to write functions using &lt;em&gt;JavaScript&lt;/em&gt; or &lt;em&gt;TypeScript&lt;/em&gt;. I would recommend using &lt;em&gt;JavaScript&lt;/em&gt; here because using ES Modules you still get type checking, and it lifts the burden to have to build every time you modify a file.&lt;/p&gt;

&lt;p&gt;As I said signals are various events Firebase listened to, and when a particular event occurs, it runs a function if you've defined it.&lt;br&gt;
Firebase provides a JavaScript package called &lt;code&gt;firebase-functions&lt;/code&gt; and it's really straightforward. It provides an interface for signals so it easily reads what it does. Let's look at a small code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;functions&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;firebase-functions/v1&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;beforeUserSignedIn&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;firebase-functions/v2/identity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onUserCreate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&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="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onBeforeSignin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;beforeUserSignedIn&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="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All functions are accessible from the &lt;code&gt;firebase-functions/v1&lt;/code&gt; path, here we use the &lt;code&gt;functions.auth.user().onCreate&lt;/code&gt; signal to run a function (&lt;code&gt;(user, context) =&amp;gt; ...&lt;/code&gt;) when a new user is created.&lt;br&gt;&lt;br&gt;
You can access most of functions from &lt;em&gt;v1&lt;/em&gt;, but a better way to access functions/signals is to use &lt;em&gt;v2&lt;/em&gt;, in the example you can see that we easily import &lt;code&gt;beforeUserSignedIn&lt;/code&gt; function/signal and use it in the code, it helps with readability.&lt;/p&gt;

&lt;p&gt;A function needs to be exported for Firebase to register it, the names &lt;code&gt;onUserCreate&lt;/code&gt; and &lt;code&gt;onBeforeSignin&lt;/code&gt; in this example are custom names, it doesn't have to be these values and you can write any name you want as far as they do not conflict.&lt;/p&gt;
&lt;h3&gt;
  
  
  Querying your firestore from functions file
&lt;/h3&gt;

&lt;p&gt;There is a difference between registering a function using &lt;code&gt;firebase-functions&lt;/code&gt; interface, and querying the firestore which can be achieve with the &lt;code&gt;firebase-admin&lt;/code&gt; package.&lt;br&gt;
While &lt;code&gt;firebase-functions&lt;/code&gt; provides a way to create functions, the &lt;code&gt;firebase-admin&lt;/code&gt; module can be used to do various things related to Firebase features, the latter helps you write various logic execution when a function is triggered. Here's an example of how to populate data in firestore when a new user is created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;functions&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;firebase-functions/v1&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;admin&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;firebase-admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onUserCreate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;onCreate&lt;/span&gt;&lt;span class="p"&gt;(&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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&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;firestore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firestore&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;userRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uid&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;premium&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="na"&gt;bookmarks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="na"&gt;website&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Emulators
&lt;/h2&gt;

&lt;p&gt;If you've installed some emulators during &lt;code&gt;firebase init&lt;/code&gt;, you can run them using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;firebase emulators:start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and access &lt;code&gt;http:localhost:4000&lt;/code&gt; to meet with the UI.&lt;/p&gt;

&lt;p&gt;From here you have to tell your app to use the various emulators endpoint rather than the remote ones&lt;br&gt;
For instance for Authentication you would use :&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getAuth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;connectAuthEmulator&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;firebase/auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firebaseAuth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getAuth&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;connectAuthEmulator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firebaseAuth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://127.0.0.1:9099&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>firebase</category>
    </item>
    <item>
      <title>I finally understand TypeScript `outDir`, `include`, `exclude` configuration properties...</title>
      <dc:creator>Valentin Degenne</dc:creator>
      <pubDate>Wed, 18 Nov 2020 21:45:41 +0000</pubDate>
      <link>https://dev.to/vdegenne/i-finally-understand-typescript-outdir-include-exclude-configuration-properties-5545</link>
      <guid>https://dev.to/vdegenne/i-finally-understand-typescript-outdir-include-exclude-configuration-properties-5545</guid>
      <description>&lt;p&gt;It took me a while to understand the behavior behind these TypeScript properties and that was driving me nuts at times. Every time I start a new project I forget what they are because you don't use them often, just when you set up your project scaffold. So that's why I write this small post, to remember.&lt;/p&gt;

&lt;p&gt;Let's use this base for our examples&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── node_modules
├── src
│   ├── main.ts
│   └── test
│       └── a.ts
└── test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  outDir
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;outDir&lt;/code&gt; is default to each individual file location. So for instance the compiler will output the file &lt;code&gt;src/test/a.ts&lt;/code&gt; as &lt;code&gt;src/test/a.js&lt;/code&gt;, quite simple.&lt;br&gt;
&lt;b&gt;It's important to understand that not using &lt;code&gt;outDir&lt;/code&gt; or using &lt;code&gt;"./"&lt;/code&gt; as its value is not the same thing !&lt;/b&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  include
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;include&lt;/code&gt; is default to &lt;code&gt;["**/*"]&lt;/code&gt; which translates to &lt;em&gt;compile every &lt;code&gt;ts&lt;/code&gt; files encountered recursively from the root (defined by the &lt;code&gt;rootDir&lt;/code&gt; property)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now here's the tricky part, when you don't use &lt;code&gt;outDir&lt;/code&gt; the interpreter uses the full paths, so for instance the file &lt;code&gt;src/test/a.ts&lt;/code&gt; (matched by &lt;code&gt;src/**/*&lt;/code&gt;) will go in the same absolute path matched by &lt;code&gt;src/**/*&lt;/code&gt; (therefore &lt;code&gt;src/test/a.js&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;But when you use &lt;code&gt;outDir&lt;/code&gt; &lt;strong&gt;the wildcards are what is really interpreted by the compiler&lt;/strong&gt;, so for instance when you use &lt;code&gt;"outDir": "./"&lt;/code&gt; the file &lt;code&gt;src/test/a.ts&lt;/code&gt; will go in the location matched by the &lt;strong&gt;wildcards&lt;/strong&gt; in the expression &lt;code&gt;src/**/*&lt;/code&gt; therefore prepended outDir &lt;code&gt;./&lt;/code&gt; plus &lt;code&gt;test/a.ts&lt;/code&gt; (not &lt;code&gt;src/test/a.ts&lt;/code&gt; !), &lt;code&gt;src&lt;/code&gt; here is not part of the match, it's just a reference to find the files.&lt;/p&gt;
&lt;h3&gt;
  
  
  exclude
&lt;/h3&gt;

&lt;p&gt;Now you may ask, if the root is my project why won't &lt;code&gt;ts&lt;/code&gt; files in &lt;code&gt;node_modules&lt;/code&gt; get compiled as well ? The reason is because the default value of &lt;code&gt;exclude&lt;/code&gt; is &lt;code&gt;node_modules&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  one example
&lt;/h1&gt;

&lt;p&gt;If you want your compilation to have this final structure :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── main.js
├── node_modules
├── src
│   ├── main.ts
│   └── test
│       └── a.ts
└── test
    └── a.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you would use &lt;code&gt;tsconfig.json&lt;/code&gt; like that&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"src/**/*"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"exclude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>typescript</category>
      <category>config</category>
    </item>
    <item>
      <title>ngxtop</title>
      <dc:creator>Valentin Degenne</dc:creator>
      <pubDate>Wed, 13 May 2020 20:15:34 +0000</pubDate>
      <link>https://dev.to/vdegenne/ngxtop-3h9b</link>
      <guid>https://dev.to/vdegenne/ngxtop-3h9b</guid>
      <description>&lt;p&gt;If you are looking for a fast way for live monitoring your server http(s) traffics here's a tool that is easy to install : &lt;strong&gt;ngxtop&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All you need is to have python and pip installed on your system :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;python python-pip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And then use &lt;code&gt;pip&lt;/code&gt; to install the tool&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;ngxtop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If the installation fails, there is a big chance that you need to update the setup tools as well and try again :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; setuptools
pip &lt;span class="nb"&gt;install &lt;/span&gt;ngxtop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After the tool is installed you can type &lt;code&gt;ngxtop&lt;/code&gt;. The tool assumes you didn't modify the access log in your nginx configuration (&lt;em&gt;/var/log/nginx/access.log&lt;/em&gt;) and run successfully.&lt;br&gt;&lt;br&gt;
Next you can visit one page of your server and you should see live update in the terminal.&lt;/p&gt;

&lt;p&gt;More details on the &lt;a href="https://github.com/lebinh/ngxtop"&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further
&lt;/h2&gt;

&lt;p&gt;If you search for a more advanced tool you should also consider checking &lt;a href="https://goaccess.io/"&gt;goaccess&lt;/a&gt;. &lt;code&gt;goaccess&lt;/code&gt; is more like a log analyzer, it is also real-time but the stats is made from all the data in the log &lt;em&gt;versus&lt;/em&gt; &lt;code&gt;ngxtop&lt;/code&gt; that starts making stats from the moment you run the command.&lt;/p&gt;

</description>
      <category>nginx</category>
      <category>monitoring</category>
      <category>webdev</category>
    </item>
    <item>
      <title>i3-dmenu-desktop and desktop applications</title>
      <dc:creator>Valentin Degenne</dc:creator>
      <pubDate>Tue, 05 May 2020 23:23:49 +0000</pubDate>
      <link>https://dev.to/vdegenne/i3-dmenu-desktop-and-desktop-applications-l86</link>
      <guid>https://dev.to/vdegenne/i3-dmenu-desktop-and-desktop-applications-l86</guid>
      <description>&lt;p&gt;Here is three locations your desktop launchers (e.g. &lt;code&gt;i3-dmenu-desktop&lt;/code&gt;) might look inside to list desktop applications :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/usr/share/applications&lt;/li&gt;
&lt;li&gt;/usr/local/share/applications&lt;/li&gt;
&lt;li&gt;~/.local/share/applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that in reality it searches for "applications" folder inside the folders listed under the environment variable &lt;code&gt;$XDG_DATA_DIRS&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>i3</category>
      <category>desktop</category>
    </item>
  </channel>
</rss>
