<?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>Forem: Kyle Parisi</title>
    <description>The latest articles on Forem by Kyle Parisi (@kyleparisi).</description>
    <link>https://forem.com/kyleparisi</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%2F79563%2F32fbdd9d-4df5-440f-9443-eff8d82eedc4.jpg</url>
      <title>Forem: Kyle Parisi</title>
      <link>https://forem.com/kyleparisi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kyleparisi"/>
    <language>en</language>
    <item>
      <title>Modals Are Promises</title>
      <dc:creator>Kyle Parisi</dc:creator>
      <pubDate>Tue, 10 Nov 2020 02:47:43 +0000</pubDate>
      <link>https://forem.com/kyleparisi/modals-are-promises-45o8</link>
      <guid>https://forem.com/kyleparisi/modals-are-promises-45o8</guid>
      <description>&lt;h1&gt;
  
  
  Can modals be treated like promises
&lt;/h1&gt;

&lt;p&gt;The answer is yes.  I can't count how many times I've coded a confirmation modal.  Every time I've been unhappy by the extra state management required to handle the open and close actions.  There must be a better way.  Promises are a natural resource for control flow.  Since a modal is almost always dictated by a user action, promises are a nice pattern.&lt;/p&gt;

&lt;h4&gt;
  
  
  Here is the tl;dr
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// get some context for the modal&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thingContext&lt;/span&gt; &lt;span class="o"&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="mi"&gt;109&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;userAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&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;// show the modal&lt;/span&gt;
  &lt;span class="nf"&gt;setDialog&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;thingContext&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;try&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;userAction&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// negative action flow&lt;/span&gt;
  &lt;span class="nf"&gt;setLoading&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="nf"&gt;setDialog&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="k"&gt;return&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="c1"&gt;// positive action flow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fi%2F3uhdlxy2lkqy4m0bq239.gif" 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%2Fi%2F3uhdlxy2lkqy4m0bq239.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kyleparisi" rel="noopener noreferrer"&gt;
        kyleparisi
      &lt;/a&gt; / &lt;a href="https://github.com/kyleparisi/promise-modal" rel="noopener noreferrer"&gt;
        promise-modal
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;promise-modal&lt;/h1&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://dev.to/kyleparisi/modals-are-promises-45o8" rel="nofollow"&gt;Article&lt;/a&gt;&lt;/p&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kyleparisi/promise-modal" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>ui</category>
      <category>react</category>
      <category>frontend</category>
      <category>protip</category>
    </item>
    <item>
      <title>15 Seconds of Fame!</title>
      <dc:creator>Kyle Parisi</dc:creator>
      <pubDate>Fri, 25 Sep 2020 17:45:20 +0000</pubDate>
      <link>https://forem.com/kyleparisi/15-seconds-of-fame-49ed</link>
      <guid>https://forem.com/kyleparisi/15-seconds-of-fame-49ed</guid>
      <description>&lt;p&gt;It's not often as a web developer that the thing you work on manifests into the physical world.  This was one of those rare times.  Earlier this week Tesla projected my company's website on a big screen behind the likes of Elon Musk and team.  &lt;/p&gt;

&lt;p&gt;For once I could show people a physical picture or youtube videos and be like, this is what I work on.  Now I'm wondering what others could do to make their website feel more physical like this.  Usually developers think in terms of urls and digital mediums.  Is there something you could do to make your projects stand out from just 1 digital property online?&lt;/p&gt;

&lt;p&gt;Have a great weekend!&lt;/p&gt;

</description>
      <category>tesla</category>
      <category>webdev</category>
      <category>fun</category>
    </item>
    <item>
      <title>Quick UI Review - Stripe Homepage</title>
      <dc:creator>Kyle Parisi</dc:creator>
      <pubDate>Thu, 06 Aug 2020 18:43:26 +0000</pubDate>
      <link>https://forem.com/kyleparisi/quick-ui-review-stripe-homepage-4bab</link>
      <guid>https://forem.com/kyleparisi/quick-ui-review-stripe-homepage-4bab</guid>
      <description>&lt;h1&gt;
  
  
  Font
&lt;/h1&gt;

&lt;p&gt;There are 7 fonts with 124(!) variations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ovQInclW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xjza8zqny01osplg3el9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ovQInclW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xjza8zqny01osplg3el9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://klim.co.nz/buy/soehne/"&gt;Sohne-var&lt;/a&gt; is the primary font.  This was probably a "&amp;gt;= 5" figure decision for them to license this font.  &lt;a href="https://www.typewolf.com/site-of-the-day/fonts/sohne"&gt;Here&lt;/a&gt; is some more detail about the font and similar types.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nX88Mw7g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d12he50sytt8hot1pr4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nX88Mw7g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d12he50sytt8hot1pr4p.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Colors
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oSsM21lN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9c1tcau1zhnwrknjiqcu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oSsM21lN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9c1tcau1zhnwrknjiqcu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;73 colors were used on that page.  This is probably high because they make almost everything on the page an html element.  This is highlighted by the fact that there are only 26 assets on the whole page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ebBgHIW8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6203gwn1hwgdk7eqyixq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ebBgHIW8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/6203gwn1hwgdk7eqyixq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Layout
&lt;/h1&gt;

&lt;p&gt;Their previous design was 2 columns with a balance on the center line of the screen.  This new design is 4 columns with a left aligned balance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pk97WF1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/n1sy6rvaaj2ln287dmke.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pk97WF1N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/n1sy6rvaaj2ln287dmke.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Notable
&lt;/h1&gt;

&lt;p&gt;The animations are smooth and intricate as they were with the previous site.  The animated text editor is pretty amazing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QiI60vDN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/13shhqdmnh8mok9e8e95.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QiI60vDN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/13shhqdmnh8mok9e8e95.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The outlines I added to illustrate that it's not a gif but actual html elements.  Looking at the source code it supports multiple languages, autocompletions, line numbers, a terminal area and more.  I can only imagine this feature took considerable amount of time to make.  Hopefully they open source it at some point.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;There is a depth of knowledge with each new design that stripe uses.  My previous post talked about the animation of the drop down from their previous version:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/kyleparisi" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hWJji69l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--RAbghDz4--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/79563/32fbdd9d-4df5-440f-9443-eff8d82eedc4.jpg" alt="kyleparisi image"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/kyleparisi/making-web-animations-9ng" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Making Web Animations&lt;/h2&gt;
      &lt;h3&gt;Kyle Parisi ・ Oct 17 '18 ・ 2 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#animations&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#css&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#frontend&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>stripe</category>
      <category>ui</category>
      <category>design</category>
    </item>
    <item>
      <title>Revisiting CPanel Hosting After 8 Years</title>
      <dc:creator>Kyle Parisi</dc:creator>
      <pubDate>Fri, 22 May 2020 12:29:02 +0000</pubDate>
      <link>https://forem.com/kyleparisi/revisiting-cpanel-hosting-after-8-years-60f</link>
      <guid>https://forem.com/kyleparisi/revisiting-cpanel-hosting-after-8-years-60f</guid>
      <description>&lt;h2&gt;
  
  
  CPanel
&lt;/h2&gt;

&lt;p&gt;Oh CPanel.  You were serverless before serverless.  You were the cloud before the "the cloud".  Things were simpler yet still very hard.  It's where I started building my first websites.  I knew nothing about servers.  Fast forward almost a decade and I know way more about servers than I care to admit.&lt;/p&gt;

&lt;p&gt;Shared hosting is still a thing and I wonder what it looks like after all this time.  So in this post I take a drive down nostalgia road and see what it was/is like to use shared hosting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;The advertised pricing is still pretty mind bending.  For less than a cup of coffee &lt;em&gt;per month&lt;/em&gt; you can host a website.  &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%2Fi%2F9to6qnfcfvm5prc2zm3z.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%2Fi%2F9to6qnfcfvm5prc2zm3z.png" alt="Pricing"&gt;&lt;/a&gt;&lt;/p&gt;
Look at that up-sell of 90 cents!



&lt;p&gt;But in reality it's more like this.&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%2Fi%2Fzt0uqqvwoqshsy59fcjj.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%2Fi%2Fzt0uqqvwoqshsy59fcjj.png" alt="Pricing really"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Experience
&lt;/h2&gt;

&lt;p&gt;The experience is still very much what I remember, just some fancier icons in the CPanel area.  The hosting company emails you your password which is pretty interesting.  I have to assume their support team has access to this information as well.&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%2Fi%2Fv1lkb6x8z34axaa0ukrb.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%2Fi%2Fv1lkb6x8z34axaa0ukrb.png" alt="Invoice"&gt;&lt;/a&gt;&lt;/p&gt;
What a beautifully formatted invoice



&lt;p&gt;Look at that invoice.  No "Cost Explorer" or "Cloud Economist" needed here.  Just 12 months of compute baby.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;p&gt;Deployment is as easy as drag and drop on an FTP client.  &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%2Fi%2F2qsc3kz7sbajaag1ob4l.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%2Fi%2F2qsc3kz7sbajaag1ob4l.png" alt="FTP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is one gotcha though.  The hosting company is just so busy setting up my cookie cutter account that they couldn't be bothered to tell me when I should expect my FTP files to show up.  So I uploaded this and waited.&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="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Retropanel.com&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Retropanel"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"author"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Kyle Parisi"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's right.  What you see there is an HTML 5 document.  Just look at my lighthouse score.&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%2Fi%2F16xby34am4w9g740vsog.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%2Fi%2F16xby34am4w9g740vsog.png" alt="Lighthouse"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cooking with gas.  Let's do something dynamic shall we.  Let me make a ☕ and I'll be right back.&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%2Fi%2Fm341dnjwwg7awwk41j4m.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm341dnjwwg7awwk41j4m.jpg" alt="Moments later"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm back!  Check it out!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://retropanel.com/" rel="noopener noreferrer"&gt;retropanel.com&lt;/a&gt;&lt;/p&gt;
The next unicorn start up



&lt;p&gt;The hardest part of making this little app was remembering how &lt;code&gt;.htaccess&lt;/code&gt; file works.  I have converted to Nginx as my reverse proxy a long time ago.  The app is a simple timestamp computation and CRUD functionality for subscribers.  Syncing the FTP files was a little awkward but I think I could manage it with some practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back To Reality
&lt;/h2&gt;

&lt;p&gt;So would I recommend anyone in this day an age use a shared hosting provider over one of the juggernauts like AWS or Google?  The pricing is a little bait and switch.  &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%2Fi%2Fyac7z8yo1xcb0z9bfmkt.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%2Fi%2Fyac7z8yo1xcb0z9bfmkt.png" alt="Amazon Lightsail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like Amazon Lightsail is very clear and doesn't change over the long run.  On the other hand, the shared hosting gives you some services like mysql, emails, free domain for the first year, crude metrics, and support.  One thing I would recommend is to not use your main contact information.  The shared hosting company I used obviously sold my information and now I'm being spammed.&lt;/p&gt;

&lt;p&gt;If I were a small local retail shop or maybe a public service with very limited resources, I would probably be ok with it.  Will I ever use CPanel for anything?  Absolutely not.  &lt;/p&gt;

&lt;p&gt;This was fun.  I hope to do it again in another 10ish years.&lt;/p&gt;

</description>
      <category>cpanel</category>
      <category>php</category>
      <category>retro</category>
    </item>
    <item>
      <title>Running Scripts at Login MacOS</title>
      <dc:creator>Kyle Parisi</dc:creator>
      <pubDate>Wed, 13 May 2020 12:52:16 +0000</pubDate>
      <link>https://forem.com/kyleparisi/running-scripts-at-login-macos-po9</link>
      <guid>https://forem.com/kyleparisi/running-scripts-at-login-macos-po9</guid>
      <description>&lt;h1&gt;
  
  
  The Problem
&lt;/h1&gt;

&lt;p&gt;Every time my computer restarts and I try to pull a git repo, I get a credentials error.  So I have to open terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-add &lt;span class="nt"&gt;-KA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This command will take your keychain ssh keys and add them to the ssh agent.  The &lt;code&gt;-K&lt;/code&gt; is not required but if you don't have a passphrase stored for an ssh key already you can enter it now.  I don't recall this being a problem in older versions of MacOS but it is a problem now.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Solution
&lt;/h1&gt;

&lt;p&gt;I decided to make use of the LaunchAgent feature.  This feature will run for the current user, at login, either a daemon or one-off scripts.  Here is what you need to do to have the above command run at login.&lt;/p&gt;

&lt;p&gt;Create the following script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

ssh-add &lt;span class="nt"&gt;-KA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Place the script somewhere you like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/scripts/startup
&lt;span class="c"&gt;# create script in ^ folder&lt;/span&gt;
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ~/scripts/startup/ssh-add.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now configure LaunchAgent&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# using sublime text editor to make this file&lt;/span&gt;
subl ~/Library/LaunchAgents/com.ssh-add.plist
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;plist&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;com.ssh-add.app&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Program&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/Users/kyleparisi/scripts/startup/ssh-add.sh&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;RunAtLoad&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note the program string above should reflect your user.  Make sure you try running it first.  Now every time you login, you no longer need to think about adding ssh keys to your agent.  You could do other things like run docker system prune commands, archive your desktop files, mount a network file system, whatever!  Enjoy!&lt;/p&gt;

</description>
      <category>macos</category>
      <category>tips</category>
      <category>launchagent</category>
    </item>
    <item>
      <title>Cynical Observations</title>
      <dc:creator>Kyle Parisi</dc:creator>
      <pubDate>Thu, 13 Feb 2020 22:41:00 +0000</pubDate>
      <link>https://forem.com/kyleparisi/cynical-observations-12nf</link>
      <guid>https://forem.com/kyleparisi/cynical-observations-12nf</guid>
      <description>&lt;p&gt;Fear of bad code makes more complex code. &lt;/p&gt;

&lt;p&gt;Docker. It works on my computer. Turns into a dance of 'docker-compose down, docker-compose rm blah, docker blah build, docker up --build'. Or if you’re a pro you’ve aliased everything. &lt;/p&gt;

&lt;p&gt;Webpack. Chrome is literally an operating system of power but we turned concatting files into a science degree. &lt;/p&gt;

&lt;p&gt;React. Where smart people write 50 line ternaries, overly complex mapping, and no reactive data.&lt;/p&gt;

&lt;p&gt;React.&lt;br&gt;
&lt;iframe class="tweet-embed" id="tweet-1256148180116353024-448" src="https://platform.twitter.com/embed/Tweet.html?id=1256148180116353024"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1256148180116353024-448');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1256148180116353024&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Typescript. For those that fear they might have to look at the browser console with 0 runtime safety. &lt;/p&gt;

&lt;p&gt;Typescript.  Using dynamic object selection negates type safety.  So much for being DRY.&lt;/p&gt;

&lt;p&gt;Kubernetes. Has your operations gotten cheaper?  Or how about that scale?&lt;/p&gt;

&lt;p&gt;Graphql. A technology optimized for not talking with your team. Screw your pagination, infinite loops, duplicated queries. It’s  good for me now. &lt;/p&gt;

&lt;p&gt;Microservices. Imagine the unix philosophy, but instead it turns into networked, tightly coupled, dependencies.&lt;/p&gt;

&lt;p&gt;Also microservices.  How many times have you synchronized deployments?&lt;/p&gt;

&lt;p&gt;Terraform. Have you had a problem in the last 30 days that terraform solves?&lt;/p&gt;

</description>
      <category>hiptech</category>
    </item>
    <item>
      <title>Simple MySQL with Elixir</title>
      <dc:creator>Kyle Parisi</dc:creator>
      <pubDate>Tue, 17 Dec 2019 13:23:08 +0000</pubDate>
      <link>https://forem.com/kyleparisi/simple-mysql-with-elixir-12n9</link>
      <guid>https://forem.com/kyleparisi/simple-mysql-with-elixir-12n9</guid>
      <description>&lt;h1&gt;
  
  
  Harder than I thought
&lt;/h1&gt;

&lt;p&gt;As with my &lt;a href="https://dev.to/kyleparisi/a-quick-dive-in-elixir-3196"&gt;last post on elixir&lt;/a&gt;, I found the default database driver to be painful.  Granted this might have been because I have been so trained into model based database interactions or even prepared query interactions.  I'm still not a fan of the ecto system; it prevents me from being able to prototype my application before hooking up the datastore.&lt;/p&gt;

&lt;p&gt;After a bit of Google research, I found a few options. &lt;em&gt;Unfortunately&lt;/em&gt;, they were very sparse in detail. The confusing part is for a functional language, the library authors seem to want to mask this with fancy macros.  For a beginner like myself, it makes mental adoption very hard.&lt;/p&gt;

&lt;p&gt;I'm also not a fan of the &lt;code&gt;Result&lt;/code&gt; struct that the library &lt;code&gt;myxql&lt;/code&gt; provides.  I just want the data from the database as a table.  Instead you'll get something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;MyXQL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="ss"&gt;columns:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="ss"&gt;connection_id:&lt;/span&gt; &lt;span class="mi"&gt;135386&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="ss"&gt;last_insert_id:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="ss"&gt;num_rows:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="ss"&gt;num_warnings:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="ss"&gt;rows:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
 &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  A simple solution
&lt;/h2&gt;

&lt;p&gt;Thankfully I stumbled upon &lt;a href="https://elixirforum.com/t/how-to-return-a-structured-json-with-column-names-and-values-in-mariaex/14657"&gt;this post&lt;/a&gt; by John Smith.  Here is how you might use this idea along with the MyXQL library which ecto uses for mysql.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&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="s2"&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="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;" LIMIT 0,100;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&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="s2"&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="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trim&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;" LIMIT &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="p"&gt;\\&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;MyXQL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;to_maps&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Insert&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;to_maps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;MyXQL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;last_insert_id:&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;columns:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;rows:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;id&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="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;id:&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Update/Delete&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;to_maps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;MyXQL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;last_insert_id:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;columns:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;rows:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="ss"&gt;:ok&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Select&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;to_maps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;MyXQL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;columns:&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;rows:&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;columns&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;into&lt;/span&gt;&lt;span class="p"&gt;(%{})&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  How to use
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Establish your connection
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# if in interactive shell&lt;/span&gt;
&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;:myapp_db&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MyXQL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="s2"&gt;"bleepbloop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;hostname:&lt;/span&gt; &lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;database:&lt;/span&gt; &lt;span class="s2"&gt;"myapp"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# if using supervision tree&lt;/span&gt;
&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Application&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;children&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="no"&gt;MyXQL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="s2"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;password:&lt;/span&gt; &lt;span class="s2"&gt;"bleepbloop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;hostname:&lt;/span&gt; &lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;database:&lt;/span&gt; &lt;span class="s2"&gt;"myapp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="ss"&gt;:myapp_db&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="no"&gt;Supervisor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Use the library
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="s2"&gt;"select * from user"&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:myapp_db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# LIMIT 0,100&lt;/span&gt;
&lt;span class="s2"&gt;"select * from user"&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;paginate&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:myapp_db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# LIMIT 100,200&lt;/span&gt;
&lt;span class="s2"&gt;"select * from user"&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:myapp_db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# use parameters&lt;/span&gt;
&lt;span class="s2"&gt;"select * from user where id = ?"&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:myapp_db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above queries all return a list of maps or a map which is easily converted into json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# select:&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="c1"&gt;# or&lt;/span&gt;
&lt;span class="p"&gt;%{}&lt;/span&gt;

&lt;span class="c1"&gt;# insert&lt;/span&gt;
&lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;id:&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# update/delete&lt;/span&gt;
&lt;span class="ss"&gt;:ok&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>elixir</category>
      <category>mysql</category>
    </item>
    <item>
      <title>A Quick Dive in Elixir</title>
      <dc:creator>Kyle Parisi</dc:creator>
      <pubDate>Wed, 25 Sep 2019 14:10:11 +0000</pubDate>
      <link>https://forem.com/kyleparisi/a-quick-dive-in-elixir-3196</link>
      <guid>https://forem.com/kyleparisi/a-quick-dive-in-elixir-3196</guid>
      <description>&lt;h1&gt;
  
  
  What is elixir?
&lt;/h1&gt;

&lt;p&gt;Yet another programming language.  There are some unique characteristics of elixir that I have not experienced with other languages.  First, the way I approach learning a new language might be of interest.  What I do is start a repo for the language or framework, in this case &lt;code&gt;elixir-kiss&lt;/code&gt; (keep it simple stupid).  &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kyleparisi" rel="noopener noreferrer"&gt;
        kyleparisi
      &lt;/a&gt; / &lt;a href="https://github.com/kyleparisi/elixir-kiss" rel="noopener noreferrer"&gt;
        elixir-kiss
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;elixir-kiss&lt;/h1&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;mix deps.get
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; terminal 1&lt;/span&gt;
iex --name a@127.0.0.1 -S mix
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; terminal 2&lt;/span&gt;
iex --name b@127.0.0.1 -S mix

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; either terminal, Node.list.  example:&lt;/span&gt;
iex(b@127.0.0.1)&lt;span class="pl-k"&gt;1&amp;gt;&lt;/span&gt; Node.list
[:&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;a@127.0.0.1&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;]&lt;/pre&gt;

&lt;/div&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kyleparisi/elixir-kiss" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;From there I start exploring basic ideas that I'm curious about and make branches off the original test bed.&lt;/p&gt;

&lt;h1&gt;
  
  
  What can you do with elixir?
&lt;/h1&gt;

&lt;p&gt;The main thing you'll find elixir being used for is some kind of distributed system.  It's a fun idea to think of a cluster of computers as a single application.  To get an application "networked" together, you can do this in a few lines.  Here is one example using a library that clusters 2 nodes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;App&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Application&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;topologies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="ss"&gt;example:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="ss"&gt;strategy:&lt;/span&gt; &lt;span class="no"&gt;Cluster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Strategy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Epmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;config:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;hosts:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:"a@127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:"b@127.0.0.1"&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="n"&gt;children&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="no"&gt;Cluster&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Supervisor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;topologies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;ClusterSupervisor&lt;/span&gt;&lt;span class="p"&gt;]]},&lt;/span&gt;
      &lt;span class="c1"&gt;# ..other children..&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="no"&gt;Supervisor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;strategy:&lt;/span&gt; &lt;span class="ss"&gt;:one_for_one&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Supervisor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a couple ways you could cluster your applications.  The above example uses a builtin strategy called &lt;a href="http://erlang.org/doc/man/epmd.html" rel="noopener noreferrer"&gt;Erlang Port Mapper Daemon&lt;/a&gt;.  Things like DNS, Multicast UDP gossip, or other API based methods can be used.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is unique about elixir?
&lt;/h1&gt;

&lt;p&gt;There are a number of unique attributes of elixir.  Elixir's control flow is heavily based on pattern matching.  This means you define functions based on the data structure being passed in.  That looks something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="s2"&gt;"/login"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;read_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Poison&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"password"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&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="n"&gt;send_resp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Poison&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode!&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;errors:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="s2"&gt;"Please provide an email."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;password:&lt;/span&gt; &lt;span class="s2"&gt;"Please provide a password"&lt;/span&gt;&lt;span class="p"&gt;}}))&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"password"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;send_resp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&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="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:invalid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"No body provided for /login"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;send_resp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Poison&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode!&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;errors:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="s2"&gt;"Please provide an email."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;password:&lt;/span&gt; &lt;span class="s2"&gt;"Please provide a password"&lt;/span&gt;&lt;span class="p"&gt;}}))&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"No password provided for /login"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;send_resp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Poison&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode!&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;errors:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;password:&lt;/span&gt; &lt;span class="s2"&gt;"Please provide a password"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&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="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"No email provided for /login"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;send_resp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Poison&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode!&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;errors:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="s2"&gt;"Please provide an email."&lt;/span&gt;&lt;span class="p"&gt;}}))&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In elixir there are no return or break statements.  The last line in a function is the return statement.  This one really caught me off guard.  Return statements are definitely designed for procedural mentality.  Not having returns really emphasizes the pattern matching functionality.&lt;/p&gt;

&lt;p&gt;Documentation is a first class citizen.  I've never seen this before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Math&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@moduledoc&lt;/span&gt; &lt;span class="sd"&gt;"""
  Provides math-related functions.

  ## Examples

      iex&amp;gt; Math.sum(1, 2)
      3

  """&lt;/span&gt;

  &lt;span class="nv"&gt;@doc&lt;/span&gt; &lt;span class="sd"&gt;"""
  Calculates the sum of two numbers.
  """&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you configure your tests to use doctests, it will actually assert against the &lt;code&gt;iex&amp;gt;&lt;/code&gt; statements.  Very cool.&lt;/p&gt;

&lt;p&gt;Running elixir can be pretty complex due to it's distributed nature.  But elixir is using erlang under the hood which happens to come with some handy &lt;em&gt;GUI&lt;/em&gt; tools built in.  You can see some of that &lt;a href="https://elixir-lang.org/getting-started/debugging.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Let it crash".  Elixir – and Erlang – encourage you to code the happy path.  Runtime errors should be allowed to crash the process. &lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lastly, elixir has a &lt;code&gt;Read Eval Print Loop&lt;/code&gt; (REPL) runtime ability that makes it easy to test thoughts and explore the running application.&lt;/p&gt;

&lt;h1&gt;
  
  
  What I don't like
&lt;/h1&gt;

&lt;p&gt;Even though elixir has reasonable types (tuples, maps, lists, etc.), doing type conversion I found to be confusing.  If I wanted to cast something from a map into a user defined struct, it did not go smoothly.  &lt;/p&gt;

&lt;p&gt;I was not very pleased with the database driver.  The most recommended interface is an abstracted library called &lt;a href="https://hexdocs.pm/ecto/Ecto.html" rel="noopener noreferrer"&gt;Ecto&lt;/a&gt;.  To use this interface you have to define repos, schemas, changesets or queries.  The queries look like some kind of &lt;code&gt;Domain Specific Language&lt;/code&gt; (DSL) and changsets is a foreign concept to me.  It's surprising that connections, prepared statements, and queries is not the suggested driver.&lt;/p&gt;

&lt;p&gt;Some library documentation, although heavily documented, doesn't seem very helpful at times.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final thoughts
&lt;/h1&gt;

&lt;p&gt;There isn't a language that is the silver bullet for all problems.  Elixir is no different.  It's still a young language, being originally created in only 2011, it's foundation is based on erlang which is much older.  I may look back at it when I have a need for distribution or clustering.&lt;/p&gt;

&lt;p&gt;Some interesting links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elixirschool.com/en/" rel="noopener noreferrer"&gt;https://elixirschool.com/en/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://engineering.dollarshaveclub.com/elixir-otp-applications-on-kubernetes-9944636b8609" rel="noopener noreferrer"&gt;https://engineering.dollarshaveclub.com/elixir-otp-applications-on-kubernetes-9944636b8609&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://tech.nextroll.com/blog/dev/2018/01/08/quaff-that-potion-saving-millions-with-elixir-and-erlang.html" rel="noopener noreferrer"&gt;http://tech.nextroll.com/blog/dev/2018/01/08/quaff-that-potion-saving-millions-with-elixir-and-erlang.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tonyc.github.io/posts/managing-external-commands-in-elixir-with-ports/" rel="noopener noreferrer"&gt;https://tonyc.github.io/posts/managing-external-commands-in-elixir-with-ports/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.carbonfive.com/2018/01/30/comparing-dynamic-supervision-strategies-in-elixir-1-5-and-1-6/" rel="noopener noreferrer"&gt;https://blog.carbonfive.com/2018/01/30/comparing-dynamic-supervision-strategies-in-elixir-1-5-and-1-6/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/plausible-insights/plausible" rel="noopener noreferrer"&gt;https://github.com/plausible-insights/plausible&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=CZWMc2cXUAw" rel="noopener noreferrer"&gt;Youtube - Hot code swapping&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://10consulting.com/presentations/building-cqrs-es-web-applications-in-elixir/#34" rel="noopener noreferrer"&gt;https://10consulting.com/presentations/building-cqrs-es-web-applications-in-elixir/#34&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>elixir</category>
      <category>basics</category>
    </item>
    <item>
      <title>Multiple Emails on GSuite</title>
      <dc:creator>Kyle Parisi</dc:creator>
      <pubDate>Mon, 15 Jul 2019 22:15:08 +0000</pubDate>
      <link>https://forem.com/kyleparisi/multiple-emails-on-gsuite-173</link>
      <guid>https://forem.com/kyleparisi/multiple-emails-on-gsuite-173</guid>
      <description>&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fph7pi5guq2eh987zbds6.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fph7pi5guq2eh987zbds6.png" alt="from"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Email Aliases
&lt;/h1&gt;

&lt;p&gt;Email aliases are one way to get more bang for your buck.  GSuite costs me $6.36/month.  For that you can have up to 30 email aliases for a single user.  So this is how you do it if you are the GSuite admin.  After logging in you can use the following links.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://admin.google.com/AdminHome?subtab=filters#ServiceSettings/service=email&amp;amp;subtab=domaindefault" rel="noopener noreferrer"&gt;Ensure Default Routing&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Default routing is a way to catch all invalid emails to your user.  If someone typos your email address, this will help you still receive the email.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://admin.google.com/AdminHome?subtab=filters#Domains:" rel="noopener noreferrer"&gt;Add Your Domain&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Here you can add your domain which is additional to your gsuite domain.  You probably don't want it to be an alias.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://admin.google.com/ac/orgunits" rel="noopener noreferrer"&gt;Add Organizational Unit&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This will allow you to make shared inboxes under google groups.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://admin.google.com/ac/users" rel="noopener noreferrer"&gt;Add Email Aliases to User&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Click on the user of interest and then "User Information".  Add whatever aliases you currently have.  At this point you'll need to wait up to an hour before the alias is added in gmail.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://mail.google.com/mail/u/0/#settings/accounts" rel="noopener noreferrer"&gt;Add Send From&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Under the "send mail as" section you should be able to add the email from the previous step.  Leave "Treat as an alias" checked and if you waited long enough from the last step, it should accept the email.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: &lt;a href="https://www.quora.com/How-do-I-add-a-profile-photo-to-an-alias-email-account-in-my-Gmail" rel="noopener noreferrer"&gt;Email profile picture&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If you want your profile picture to show in gmail clients, this is how you would do that.&lt;/p&gt;

</description>
      <category>gsuite</category>
      <category>indiehackers</category>
      <category>protip</category>
    </item>
    <item>
      <title>Charles Proxy</title>
      <dc:creator>Kyle Parisi</dc:creator>
      <pubDate>Tue, 14 May 2019 17:38:12 +0000</pubDate>
      <link>https://forem.com/kyleparisi/charles-proxy-1pnb</link>
      <guid>https://forem.com/kyleparisi/charles-proxy-1pnb</guid>
      <description>&lt;h2&gt;
  
  
  Charles What?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.charlesproxy.com/"&gt;Charles Proxy&lt;/a&gt; is a GUI to "man-in-the-middle" (MITM) yourself by snooping and/or modifying your own HTTP(S) requests. Usually, this is seen as a problem. However, it can be an immensely powerful tool for front-end development. I will explain what can be done with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Updates Before Go-Live
&lt;/h2&gt;

&lt;p&gt;I used to maintain a JavaScript file which was deployed on hundreds of e-commerce websites. There were times I needed to know if my logic was going to work before deploying. So, in this case, I would "Map Local" the JavaScript file. This allowed me to map HTTP(S) requests for the remote JavaScript file to a local .js file instead. This is how I would know that my code was solid, before deployment.&lt;/p&gt;

&lt;p&gt;A customer once claimed my JavaScript was breaking their website. To prove that that was not the case, I quickly mapped the production .js file to a blank file, and proved that their website was still broken even with my .js file having no content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Production Level Data
&lt;/h2&gt;

&lt;p&gt;Unfortunately, a production environment sometimes includes data which is missing within development or UAT environments. Perhaps an edge-case of the system is the reason. If I need to test a front-end change with this set of data, I could use the "Rewrite" feature of Charles to replace the body of a development or UAT request to be whatever data that I need to test. This often times is much faster to do, rather than mocking up the data for the interface to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Backends
&lt;/h2&gt;

&lt;p&gt;In the last example, let's say you spun up a resource in Europe (you know because of privacy laws) for your backend. You want to test end-to-end that the new region is working, before pointing your library to this new region. In this case, you can "Map Remote". Just swap your US region DNS with your EU region DNS.&lt;/p&gt;

&lt;h2&gt;
  
  
  That's Charles
&lt;/h2&gt;

&lt;p&gt;Hopefully this illustrates a valuable tool for you. Sometimes working with the front-end of the web can feel like having super-powers. You can do anything you want and most likely no one will know. The same cannot always be said when you make changes to backend technologies.&lt;/p&gt;

</description>
      <category>proxy</category>
      <category>mitm</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Creative Selection</title>
      <dc:creator>Kyle Parisi</dc:creator>
      <pubDate>Fri, 29 Mar 2019 23:06:01 +0000</pubDate>
      <link>https://forem.com/kyleparisi/creative-selection-gf2</link>
      <guid>https://forem.com/kyleparisi/creative-selection-gf2</guid>
      <description>&lt;h1&gt;
  
  
  An inside look
&lt;/h1&gt;

&lt;p&gt;Creative Selection by Ken Kocienda is a book about working inside Apple as a software developer.  I must say Ken's creditability is pretty amazing given that he wrote the iOS keyboard software.  His book takes a unique perspective on what it was like working at Apple.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prototyping
&lt;/h2&gt;

&lt;p&gt;The first thing that I think is important, he emphasized the routine of demoing software.  It wasn't just one demo and the work was done, it was an iterative approach to meet the quality and taste of Apple.  I empathize with this idea coming from the mechanical engineering background.  Prototyping is essential to making anything physical.  You'll never get it right the first time.  The story behind making the iOS keyboard is amazing.  I took it completely for granted how something which looks so obvious nearly killed the project entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design
&lt;/h2&gt;

&lt;p&gt;A quote really resonated with me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Most people make the mistake of thinking design is what it looks like. People think it’s this veneer – that the designers are handed this box and told, “Make it look good!” That’s not what we think design is. It’s not just what it looks like and feels like. Design is how it works.&lt;/p&gt;
Steve Jobs


&lt;/blockquote&gt;

&lt;p&gt;Ken's book describes how this ethos was applied in his work.&lt;/p&gt;

&lt;h2&gt;
  
  
  An amazing summation
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;A small group of people built a work culture based on applying the seven essential elements through an ongoing process of creative selection&lt;/p&gt;
Ken Kocienda


&lt;/blockquote&gt;

&lt;p&gt;To find out what the seven essential elements are you'll have to read the book 😉.  The book is very easy to read and not overly technical.  Happy reading!&lt;/p&gt;

</description>
      <category>book</category>
      <category>apple</category>
    </item>
    <item>
      <title>JS Proxies</title>
      <dc:creator>Kyle Parisi</dc:creator>
      <pubDate>Tue, 12 Mar 2019 13:12:22 +0000</pubDate>
      <link>https://forem.com/kyleparisi/js-proxies-gm0</link>
      <guid>https://forem.com/kyleparisi/js-proxies-gm0</guid>
      <description>&lt;h1&gt;
  
  
  You might be using proxies without knowing it
&lt;/h1&gt;

&lt;p&gt;If you write an application in Vuejs or from what I can tell, React was using proxies before.  Proxies are like giving your objects (only objects) super powers.  Let me describe what you can do with an example.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dyn
&lt;/h1&gt;

&lt;p&gt;In a previous post, I talk about &lt;a href="https://dev.to/kyleparisi/my-take-on-dynamodb-3nc4"&gt;my take on dynamodb&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Every time I look at the Dynamodb SDK docs, I think 'man this is an over engineered hot mess'.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The API is not intuitive and requires googling every time.  Every operation requires a js object to be sent to Dynamodb's API.  It made me wonder if I could mask the js object with a js proxy.  I think it provides for a cleaner and more memorable interface.  The idea started with a single signature.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create[table] = {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Could I create a dynamodb record with that as simple interface?&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;create&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Proxy&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="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&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;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;target&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="na"&gt;set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prop&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="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;Item&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="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;docClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;promise&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;Hopefully you can see the above generates the parameters required for dynamodb's docClient (so I don't have to look them up).  It also stores the promise in the object (&lt;code&gt;create.promise&lt;/code&gt;) if you need to know when it's done creating the object.&lt;/p&gt;

&lt;p&gt;It worked.  So I made more operations into a library I called, Dyn:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/kyleparisi" rel="noopener noreferrer"&gt;
        kyleparisi
      &lt;/a&gt; / &lt;a href="https://github.com/kyleparisi/dyn" rel="noopener noreferrer"&gt;
        dyn
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Experiment library to read from dynamodb
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Dyn&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;Super crude idea for a library to talk with dynamodb.  Does not handle paging at the moment.  An interesting use of js proxies.&lt;/p&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm i @nargella/dyn&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-v"&gt;Dyn&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;require&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;"@nargella/dyn"&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-c1"&gt;AWS&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;require&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;"aws-sdk"&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-c1"&gt;AWS&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;config&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;region&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-s"&gt;"us-east-1"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  reader&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  query&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  queryByIndex&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  queryAndFilter&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  scan&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  create&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  update&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  updateConditionally&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  del
&lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-k"&gt;new&lt;/span&gt; &lt;span class="pl-v"&gt;Dyn&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-k"&gt;new&lt;/span&gt; &lt;span class="pl-c1"&gt;AWS&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;DynamoDB&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;DocumentClient&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;See &lt;a href="https://github.com/kyleparisi/dyn_data" rel="noopener noreferrer"&gt;dyn_data&lt;/a&gt; for some data.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Create&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// create[table] = {}&lt;/span&gt;

&lt;span class="pl-s1"&gt;create&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;ProductCatalog&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;Id&lt;/span&gt;: &lt;span class="pl-c1"&gt;500&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;Price&lt;/span&gt;: &lt;span class="pl-c1"&gt;222&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;ProductCategory&lt;/span&gt;: &lt;span class="pl-s"&gt;"Bicycle"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;Title&lt;/span&gt;: &lt;span class="pl-s"&gt;"99-Bike-212"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;BicycleType&lt;/span&gt;: &lt;span class="pl-s"&gt;"Hybrid"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;Brand&lt;/span&gt;: &lt;span class="pl-s"&gt;"Brand 212"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;Color&lt;/span&gt;: &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s"&gt;"Red"&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;Description&lt;/span&gt;: &lt;span class="pl-s"&gt;"212 Description"&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Read&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Basic key/value:&lt;/p&gt;

&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// reader[table]({partitionkey: value, [sortkey: value]})&lt;/span&gt;
&lt;span class="pl-k"&gt;await&lt;/span&gt; &lt;span class="pl-s1"&gt;reader&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;Movies&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/kyleparisi/dyn" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h1&gt;
  
  
  Gotchas
&lt;/h1&gt;

&lt;p&gt;Proxies are very cool but there are 2 things that caught me off guard.  Firstly, the root object gives you nothing.  In the above example I can't proxy the &lt;code&gt;create&lt;/code&gt; key to anything.  Secondly, you can't nest properties as a single proxy definition.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftuoxz83gnwdaoxn9s09u.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftuoxz83gnwdaoxn9s09u.png" alt="Proxy design"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>proxies</category>
    </item>
  </channel>
</rss>
