<?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: Kevin Le</title>
    <description>The latest articles on Forem by Kevin Le (@codeprototype).</description>
    <link>https://forem.com/codeprototype</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%2F25318%2F0d5060c7-d2e6-4144-84cd-07d733b20df2.png</url>
      <title>Forem: Kevin Le</title>
      <link>https://forem.com/codeprototype</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/codeprototype"/>
    <language>en</language>
    <item>
      <title>Create an Azure Pipelines to deploy Docker image for Azure App Service</title>
      <dc:creator>Kevin Le</dc:creator>
      <pubDate>Fri, 06 Aug 2021 20:16:00 +0000</pubDate>
      <link>https://forem.com/codeprototype/create-an-azure-pipelines-to-deploy-docker-image-for-azure-app-service-4f15</link>
      <guid>https://forem.com/codeprototype/create-an-azure-pipelines-to-deploy-docker-image-for-azure-app-service-4f15</guid>
      <description>&lt;p&gt;This article details how to containerize an app, create an App Service in Azure and configure it to pull the Docker image from the Azure Container Registry (ACR). How the Docker image gets deployed from our code to ACR is a result of us creating a deployment pipeline using Azure Pipelines. &lt;/p&gt;

&lt;p&gt;The benefit is instead of manually pushing the locally-built Docker image to ACR after some code changes, we now have an automated Continuous Integration/Continuous Deployment (CI/CD) process. &lt;/p&gt;

&lt;p&gt;The workflow can be described as follow: We write the code on our Dev computer, build and run the Docker image locally. Once we do a &lt;code&gt;git&lt;/code&gt; push of the code to a &lt;code&gt;git&lt;/code&gt; repo, Azure Pipelines performs the build on some agent machine and deploys the Docker image to ACR. Since the App Service has also already been configured for Continuous Deployment, it will pull the image from the ACR automatically. Essentially we have a pipeline from code to repo to Docker image to ACR to App Service.&lt;/p&gt;

&lt;p&gt;1) We start with writing an app. What app to write is not the focal point of this article. But to have something to start with, we will create an out-of-the-box NextJS app using &lt;code&gt;npx create-next-app&lt;/code&gt;. We could have done with an ASP.Net core app and everything will be just the same. So let's start:&lt;/p&gt;

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

npx create-next-app mysample
cd mysample
npm run build


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

&lt;/div&gt;

&lt;p&gt;2) We will create a Docker image for this and run in a local Docker container. To do so, we will create a &lt;code&gt;Dockerfile&lt;/code&gt; and a &lt;code&gt;docker-compose.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Here's the &lt;code&gt;Dockerfile&lt;/code&gt;&lt;/p&gt;

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

FROM node:14 as BUILD_IMAGE
WORKDIR /var/www/app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
RUN yarn build

# remove dev dependencies
RUN npm prune --production

FROM node:14
WORKDIR /var/www/app
COPY --from=BUILD_IMAGE /var/www/app/package.json ./package.json
COPY --from=BUILD_IMAGE /var/www/app/node_modules ./node_modules
COPY --from=BUILD_IMAGE /var/www/app/.next ./.next
COPY --from=BUILD_IMAGE /var/www/app/public ./public

EXPOSE 3000
CMD ["yarn", "start"]


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

&lt;/div&gt;

&lt;p&gt;And &lt;code&gt;docker-compose.yml&lt;/code&gt; file&lt;/p&gt;

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

version: '3.4'

services:
  app:
    build:
      context: .
      dockerfile: ./Dockerfile
    ports:
      - 80:3000
    env_file: .env
    command:
      sh -c 'yarn start'


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

&lt;/div&gt;

&lt;p&gt;3) Now we can run the Docker locally with the command&lt;/p&gt;

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

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

&lt;/div&gt;

&lt;p&gt;It should work if you point the browser to &lt;code&gt;http://localhost&lt;/code&gt; (that's port 80 not 3000)&lt;/p&gt;

&lt;p&gt;4) All the next steps that we're about to do can be done with the UI in &lt;a href="//portal.azure.com"&gt;Azure Portal&lt;/a&gt;, but we will use &lt;a href="https://docs.microsoft.com/en-us/cli/azure/" rel="noopener noreferrer"&gt;Azure CLI&lt;/a&gt; as much as possible. Also, I will name my &lt;code&gt;Resource Group&lt;/code&gt; and &lt;code&gt;App Service Plan&lt;/code&gt; as &lt;code&gt;MyResourceGroup&lt;/code&gt; and &lt;code&gt;MyLinuxPlan&lt;/code&gt; respectively. If you already have a Resource Group and App Service plan, you can continue using them. Or you can follow next step and substitute with names of your own choosing.&lt;/p&gt;

&lt;p&gt;Let's create a Resource Group called &lt;code&gt;MyResourceGroup&lt;/code&gt;&lt;/p&gt;

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

az group create -l westus -n MyResourceGroup


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

&lt;/div&gt;

&lt;p&gt;Now we create a Linux App Service Plan called &lt;code&gt;MyLinuxPlan&lt;/code&gt; with 2 workers&lt;/p&gt;

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

az appservice plan create -g MyResourceGroup -n MyLinuxPlan \
    --is-linux --number-of-workers 2 --sku S1


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

&lt;/div&gt;

&lt;p&gt;To create a Resource Group, refer to this &lt;a href="https://docs.microsoft.com/en-us/cli/azure/group?view=azure-cli-latest#az_group_create" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;br&gt;
To create an App Service Plan refer to this &lt;a href="https://docs.microsoft.com/en-us/cli/azure/appservice/plan?view=azure-cli-latest#az_appservice_plan_create" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5) Now we create an Azure Container Registry called &lt;code&gt;mysampleacr&lt;/code&gt;&lt;/p&gt;

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

az acr create --name mysampleacr --resource-group \
    MyResourceGroup --sku Basic --admin-enabled true


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

&lt;/div&gt;

&lt;p&gt;At this point, we now have an ACR but no image has been pushed to it and no App Service has been created. This is where my approach starts to differ from that in Azure documentation. &lt;/p&gt;

&lt;p&gt;This is OK because we don't want to push the Docker image to ACR manually. Instead we will set up the Azure Pipeline now.&lt;/p&gt;

&lt;p&gt;6) Let's go to &lt;a href="https://dev.azure.com" rel="noopener noreferrer"&gt;https://dev.azure.com&lt;/a&gt;, navigate to the &lt;code&gt;Pipeline&lt;/code&gt; page and create a new Pipeline as shown in the next picture:&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%2F98vdhl0x90nigi8sgojb.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%2F98vdhl0x90nigi8sgojb.png" alt="Azure Pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;7) Then specify &lt;code&gt;Where is you code?&lt;/code&gt; when prompted.&lt;/p&gt;

&lt;p&gt;8) At the page &lt;code&gt;Configure your pipeline&lt;/code&gt;, scroll down and click on "Show more". Then select &lt;code&gt;Docker Build and push an image to Azure Container Registry&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;9) Select your Subscription and &lt;code&gt;Continue&lt;/code&gt;. You might be prompted to login again.&lt;/p&gt;

&lt;p&gt;10) Now select your Container Registry. If you follow this example, earlier we name it &lt;code&gt;mysampleacr&lt;/code&gt;. For image name, let's name it &lt;code&gt;mysampleimg&lt;/code&gt;. Then click on &lt;code&gt;Validate and configure&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;11) We should get a generated &lt;code&gt;azure-pipelines.yml&lt;/code&gt; file with contents similar to the one below&lt;/p&gt;

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

# Docker
# Build and push an image to Azure Container Registry
# https://docs.microsoft.com/azure/devops/pipelines/languages/docker

trigger:
- main

resources:
- repo: self

variables:
  # Container registry service connection established during pipeline creation
  dockerRegistryServiceConnection: 'b0...a4'
  imageRepository: 'mysampleimg'
  containerRegistry: 'mysampleacr.azurecr.io'
  dockerfilePath: '**/Dockerfile'
  tag: '$(Build.BuildId)'

  # Agent VM image name
  vmImageName: 'ubuntu-latest'

stages:
- stage: Build
  displayName: Build and push stage
  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: $(vmImageName)
    steps:
    - task: Docker@2
      displayName: Build and push an image to container registry
      inputs:
        command: buildAndPush
        repository: $(imageRepository)
        dockerfile: $(dockerfilePath)
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(tag)


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

&lt;/div&gt;

&lt;p&gt;We need to make a couple of changes and then we can &lt;code&gt;Save and run&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the above file, look for the line &lt;code&gt;tag: '$(Build.BuildId)'&lt;/code&gt; and add a line below it. It will now show&lt;/p&gt;

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

tag: '$(Build.BuildId)'
latestTag: 'latest'


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

&lt;/div&gt;

&lt;p&gt;In the last 2 lines of the file, change from &lt;/p&gt;

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

tags: |
  $(tag)


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

&lt;/div&gt;

&lt;p&gt;to&lt;/p&gt;

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

tags: |
  $(latestTag)


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

&lt;/div&gt;

&lt;p&gt;The resulting/modified &lt;code&gt;azure-pipelines.yml&lt;/code&gt; file should now look something like&lt;/p&gt;

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

# Docker
# Build and push an image to Azure Container Registry
# https://docs.microsoft.com/azure/devops/pipelines/languages/docker

trigger:
- main

resources:
- repo: self

variables:
  # Container registry service connection established during pipeline creation
  dockerRegistryServiceConnection: 'b0...a4'
  imageRepository: 'mysampleimg'
  containerRegistry: 'mysampleacr.azurecr.io'
  dockerfilePath: '**/Dockerfile'
  tag: '$(Build.BuildId)'
  latestTag: 'latest'

  # Agent VM image name
  vmImageName: 'ubuntu-latest'

stages:
- stage: Build
  displayName: Build and push stage
  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: $(vmImageName)
    steps:
    - task: Docker@2
      displayName: Build and push an image to container registry
      inputs:
        command: buildAndPush
        repository: $(imageRepository)
        dockerfile: $(dockerfilePath)
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(latestTag)


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

&lt;/div&gt;

&lt;p&gt;Now we can &lt;code&gt;Save and run&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;12) When the run finishes, we can verify there is an image in the ACR by running the following commands (one by one)&lt;/p&gt;

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

az acr repository list -n mysampleacr

az acr repository show -n mysampleacr \
  --repository mysampleimg

az acr repository show -n mysampleacr  \
  --repository mysampleimg:latest


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

&lt;/div&gt;

&lt;p&gt;For more help on &lt;code&gt;az acr repository&lt;/code&gt; commands, please refer to &lt;a href="https://docs.microsoft.com/en-us/cli/azure/acr/repository?view=azure-cli-latest#az_acr_repository_list" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/cli/azure/acr/repository?view=azure-cli-latest#az_acr_repository_list&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;13) Now we can create an App Service and tell it to pull from the latest image &lt;code&gt;mysampleimg:latest&lt;/code&gt; from the ACR &lt;code&gt;mysampleacr&lt;/code&gt;.&lt;/p&gt;

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

az webapp create --resource-group MyResourceGroup --plan MyLinuxPlan --name mysample --deployment-container-image-name mysampleacr.azurecr.io/mysampleimg:latest


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

&lt;/div&gt;

&lt;p&gt;14) To ensure when a new image is pushed to the ACR, the App Service will automatically pull the latest image, go to &lt;a href="https://portal.azure.com" rel="noopener noreferrer"&gt;Azure Portal&lt;/a&gt;, navigate to the App Service blade and make sure &lt;code&gt;Continuous Deployment&lt;/code&gt; is on.&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%2F1iuowr923axifra0g2va.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%2F1iuowr923axifra0g2va.png" alt="App Service Continuous Deployment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;References (A little difficult to read for me, but that's just my opinion):&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/app-service/quickstart-nodejs?pivots=platform-linux" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/app-service/quickstart-nodejs?pivots=platform-linux&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/architecture/example-scenario/apps/devops-dotnet-webapp" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/architecture/example-scenario/apps/devops-dotnet-webapp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/developer/javascript/tutorial/deploy-nodejs-azure-app-service-with-visual-studio-code?tabs=bash" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/developer/javascript/tutorial/deploy-nodejs-azure-app-service-with-visual-studio-code?tabs=bash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/app-service/quickstart-custom-container?tabs=node&amp;amp;pivots=container-linux" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/app-service/quickstart-custom-container?tabs=node&amp;amp;pivots=container-linux&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>azure</category>
      <category>appservice</category>
    </item>
    <item>
      <title>A Docker container to serve directory with upload capability</title>
      <dc:creator>Kevin Le</dc:creator>
      <pubDate>Mon, 19 Jul 2021 15:49:45 +0000</pubDate>
      <link>https://forem.com/codeprototype/a-docker-container-to-serve-directory-with-upload-capability-1och</link>
      <guid>https://forem.com/codeprototype/a-docker-container-to-serve-directory-with-upload-capability-1och</guid>
      <description>&lt;p&gt;Sometime we just need a simple solution to serve some directory but also allow upload capability. I just created one and the source code is &lt;a href="https://github.com/khle/serve-dir-upload"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The heavy lifting is done by &lt;a href="https://github.com/vercel/serve-handler"&gt;vercel/serve-handler&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The use case for me is I use it to share books, PDFs, and other documents among all of the computers in my local network. I can retrieve and upload from any of my computers. &lt;/p&gt;

</description>
      <category>docker</category>
      <category>node</category>
    </item>
    <item>
      <title>Store and share passwords among Linux, Mac and Windows in a  local network</title>
      <dc:creator>Kevin Le</dc:creator>
      <pubDate>Sun, 18 Jul 2021 14:12:45 +0000</pubDate>
      <link>https://forem.com/codeprototype/store-and-share-passwords-among-linux-mac-and-windows-in-a-local-network-3gl5</link>
      <guid>https://forem.com/codeprototype/store-and-share-passwords-among-linux-mac-and-windows-in-a-local-network-3gl5</guid>
      <description>&lt;p&gt;There are many cloud-based Password Manager solutions, free and paid. One of the free ones I like the most is &lt;a href="https://bitwarden.com/"&gt;BitWarden&lt;/a&gt;. Then there's also &lt;a href="https://keepass.info/"&gt;KeePass&lt;/a&gt; which I think is only a desktop application. Those are battlefield-tested solutions. Before I go on, I'd recommend you would consider those solutions as well. &lt;/p&gt;

&lt;p&gt;But those solutions do not meet the requirements for my use case. I use all 3 kind of computers Linux, Mac and Windows. The motivation for me is at any given time, when I'm prompted for a password, I want to have a quick and convenient way to retrieve it, regardless of which computer and OS I happen to be on. For me that would be using a &lt;a href="https://en.wikipedia.org/wiki/Command-line_interface"&gt;CLI&lt;/a&gt;. Secondly, I do not want my passwords to leave my local network. Finally, if I create a new password on one computer, I want to be able to replicate it to all of my computers.&lt;/p&gt;

&lt;p&gt;The core of my solution is a simple Password Manager called &lt;a href="https://github.com/dylanaraps/pash"&gt;pash&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Linux
&lt;/h3&gt;

&lt;p&gt;There's no installation. On Linux, simply create an &lt;code&gt;executable file&lt;/code&gt; at &lt;code&gt;/usr/local/bin&lt;/code&gt; called &lt;code&gt;pash&lt;/code&gt; and copy the content from &lt;a href="https://github.com/dylanaraps/pash/blob/master/pash"&gt;https://github.com/dylanaraps/pash/blob/master/pash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make it executable by calling &lt;code&gt;chmod&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x pash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;pash&lt;/code&gt; is easy. Just type &lt;code&gt;pash&lt;/code&gt; and it will show how to use it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pash
pash 2.3.0 - simple password manager.

=&amp;gt; [a]dd  [name] - Create a new password entry.
=&amp;gt; [c]opy [name] - Copy entry to the clipboard.
=&amp;gt; [d]el  [name] - Delete a password entry.
=&amp;gt; [l]ist        - List all entries.
=&amp;gt; [s]how [name] - Show password for an entry.
=&amp;gt; [t]ree        - List all entries in a tree.

Using a key pair:  export PASH_KEYID=XXXXXXXX
Password length:   export PASH_LENGTH=50
Password pattern:  export PASH_PATTERN=_A-Z-a-z-0-9
Store location:    export PASH_DIR=~/.local/share/pash
Clipboard tool:    export PASH_CLIP='xclip -sel c'
Clipboard timeout: export PASH_TIMEOUT=15 ('off' to disable)

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mac
&lt;/h3&gt;

&lt;p&gt;On a Mac, &lt;code&gt;GnuPG&lt;/code&gt; &lt;a href="https://stackoverflow.com/a/27042267/1244013"&gt;is not installed by default&lt;/a&gt;, so we must first install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install gnupg gnupg2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then carry out the rest just like in the Linux section above.&lt;/p&gt;

&lt;h3&gt;
  
  
  Windows
&lt;/h3&gt;

&lt;p&gt;On Windows, we need Windows 10 Pro edition. Then &lt;a href="https://duckduckgo.com/?t=ffab&amp;amp;q=install+wsl2+windows+10&amp;amp;ia=web"&gt;install WSL2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Again, carry out the rest just like in the Linux section above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replication
&lt;/h2&gt;

&lt;p&gt;Now I can create a password on any one of the computers, be it Linux, Mac or Windows. Next I want to replicate it easily to the rest of the computers in my local network. In that way, the passwords are always available. Since I do not want the passwords to leave my local network, I don't want to copy to Google Drive or OneDrive or something like that. And since I want the replication process to be easy, I don't want to copy to a USB drive, eject, carry around, plug back in, etc.&lt;/p&gt;

&lt;p&gt;What I will do is install OpenSSH server on my Linux computer, which seems like the most sensible approach.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install openssh-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then on my Mac and  Windows/WSL2, I just create a couple of executable files called &lt;code&gt;pashpush&lt;/code&gt; and &lt;code&gt;pashpull&lt;/code&gt; in &lt;code&gt;\usr\local\bin&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/sh
#
# pashpush
scp ~/.local/share/pash/$1.gpg kevin@linux-host:~/.local/share/pash/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/sh
#
# pashpull
scp kevin@linux-host:~/.local/share/pash/$1.gpg ~/.local/share/pash/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run &lt;code&gt;chmod +x&lt;/code&gt; as before with the program &lt;code&gt;pash&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;pashpush&lt;/code&gt; and &lt;code&gt;pashpull&lt;/code&gt; is easy&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pashpush some-password
pashpull another-password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively if you don't like CLI, there are GUI options such as &lt;a href="https://winscp.net/eng/index.php"&gt;WinSCP&lt;/a&gt; on Windows and &lt;a href="https://panic.com/transmit/"&gt;Transmit by Panic&lt;/a&gt; on Mac and &lt;a href="https://filezilla-project.org/"&gt;Filezilla&lt;/a&gt; on both.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>macos</category>
      <category>wsl2</category>
    </item>
    <item>
      <title>Type-safely parsing JSON to a TypeScript Interface</title>
      <dc:creator>Kevin Le</dc:creator>
      <pubDate>Sat, 17 Apr 2021 12:48:47 +0000</pubDate>
      <link>https://forem.com/codeprototype/safely-parsing-json-to-a-typescript-interface-3lkj</link>
      <guid>https://forem.com/codeprototype/safely-parsing-json-to-a-typescript-interface-3lkj</guid>
      <description>&lt;p&gt;Let's say we're working with a REST API that returns a JSON string representing a user. The JSON API agrees to a contract that it returns a string &lt;code&gt;firstName&lt;/code&gt;, a string &lt;code&gt;lastName&lt;/code&gt; and a number &lt;code&gt;accountBalance&lt;/code&gt;. We model the user as an &lt;code&gt;Interface&lt;/code&gt; in TypeScript as follow:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 ts
interface User {
    firstName: string;
    lastName: string;
    accountBalance: number;
}


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

&lt;/div&gt;
&lt;p&gt;The following code is sufficient if we always have the &lt;code&gt;happy path&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 ts
const json = '{"firstName": "Kevin", "lastName": "Le", "accountBalance": 100}'
const user: User = JSON.parse(json)


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

&lt;/div&gt;
&lt;p&gt;But things can go wrong on the API side. The &lt;code&gt;json&lt;/code&gt; string returned could be:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 ts
const json  '{"firstName": "Kevin", "lastName": "Le", "accountBalance": "100"}'
const user: User = JSON.parse(json)
console.log(user)


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

&lt;/div&gt;
&lt;p&gt;The code does not blow up because &lt;code&gt;accountBalance&lt;/code&gt; is now being treated as an &lt;code&gt;any&lt;/code&gt; instead of a &lt;code&gt;number&lt;/code&gt;. But this "forgiving" behavior leads to other problem downstream:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 ts
const balanceAfterInterest = user.accountBalance + user.accountBalance * 0.05
console.log(balanceAfterInterest) //1005


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

&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;balanceAfterInterest&lt;/code&gt; is only supposed to be &lt;code&gt;105&lt;/code&gt;. A better approach is to catch this problem early and handle it immediately and appropriately.&lt;/p&gt;

&lt;p&gt;Head over to &lt;a href="https://app.quicktype.io" rel="noopener noreferrer"&gt;https://app.quicktype.io&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Paste the string &lt;code&gt;{"firstName": "Kevin", "lastName": "Le", "accountBalance": 100}&lt;/code&gt; to the left pane. Type &lt;code&gt;User&lt;/code&gt; as the &lt;code&gt;Name&lt;/code&gt;, and select &lt;code&gt;JSON&lt;/code&gt; as the &lt;code&gt;Source type&lt;/code&gt;. &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%2Flluszrt4fdt8f94ilp63.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%2Flluszrt4fdt8f94ilp63.png" alt="Alt Text" width="472" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the box on the right, select &lt;code&gt;TypeScript&lt;/code&gt; as the &lt;code&gt;Language&lt;/code&gt; and make sure &lt;code&gt;Verify JSON.parse results at runtime&lt;/code&gt; is turned-on. Quicktype will generate the resulting code with instruction on how to use it in the middle.&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%2F2jomsc5j4jowdj90y1na.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%2F2jomsc5j4jowdj90y1na.png" alt="Alt Text" width="272" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now the following code can be much safer:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 ts
import { Convert, User } from "./user";

const json =
  '{"firstName": "Kevin", "lastName": "Le", "accountBalance": "100"}';

try {
  const user = Convert.toUser(json);
  console.log(user);
} catch (e) {
  console.log("Handle error", e);
}


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

&lt;/div&gt;
&lt;p&gt;The exception is now caught and handled early:&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%2Fvi3jrdwbanb8lh9d3jvx.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%2Fvi3jrdwbanb8lh9d3jvx.png" alt="Alt Text" width="371" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The generated code by &lt;a href="https://app.quicktype.io" rel="noopener noreferrer"&gt;quicktype&lt;/a&gt; for &lt;code&gt;user.js&lt;/code&gt; is:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



</description>
      <category>typescript</category>
    </item>
    <item>
      <title>Answer: What are express.json() and express.urlencoded()?</title>
      <dc:creator>Kevin Le</dc:creator>
      <pubDate>Wed, 03 Feb 2021 14:16:57 +0000</pubDate>
      <link>https://forem.com/codeprototype/answer-what-are-express-json-and-express-urlencoded-g24</link>
      <guid>https://forem.com/codeprototype/answer-what-are-express-json-and-express-urlencoded-g24</guid>
      <description>&lt;p&gt;Good explanation&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__stackexchange--container"&gt;
  &lt;div class="ltag__stackexchange--title-container"&gt;
    
      &lt;div class="ltag__stackexchange--title"&gt;
        &lt;div class="ltag__stackexchange--header"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7Gn-iPj_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/stackoverflow-logo-b42691ae545e4810b105ee957979a853a696085e67e43ee14c5699cf3e890fb4.svg" alt=""&gt;
          &lt;a href="https://stackoverflow.com/questions/23259168/what-are-express-json-and-express-urlencoded/51844327#51844327" rel="noopener noreferrer"&gt;
            &lt;span class="title-flare"&gt;answer&lt;/span&gt; re: What are express.json() and express.urlencoded()?
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="ltag__stackexchange--post-metadata"&gt;
          &lt;span&gt;Aug 14 '18&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;a class="ltag__stackexchange--score-container" href="https://stackoverflow.com/questions/23259168/what-are-express-json-and-express-urlencoded/51844327#51844327" rel="noopener noreferrer"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y9mJpuJP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/stackexchange-arrow-up-eff2e2849e67d156181d258e38802c0b57fa011f74164a7f97675ca3b6ab756b.svg" alt=""&gt;
        &lt;div class="ltag__stackexchange--score-number"&gt;
          400
        &lt;/div&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wif5Zq3z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/stackexchange-arrow-down-4349fac0dd932d284fab7e4dd9846f19a3710558efde0d2dfd05897f3eeb9aba.svg" alt=""&gt;
      &lt;/a&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--body"&gt;
    
&lt;p&gt;Here is the explanation that should clear doubts on &lt;code&gt;express.json()&lt;/code&gt; and &lt;code&gt;express.urlencoded()&lt;/code&gt; and the use of body-parser.  It took me some time to figure this out.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What is Middleware?  It is those methods/functions/operations that are called BETWEEN processing the Request and sending the Response in your application method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When talking…&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
    
  &lt;/div&gt;
  &lt;div class="ltag__stackexchange--btn--container"&gt;
    &lt;a href="https://stackoverflow.com/questions/23259168/what-are-express-json-and-express-urlencoded/51844327#51844327" class="ltag__stackexchange--btn" rel="noopener noreferrer"&gt;Open Full Answer&lt;/a&gt;
  &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>express</category>
    </item>
    <item>
      <title>Learn Xamarin.Forms Control Template by making a Button with built-in Loading Indicator in 4 steps</title>
      <dc:creator>Kevin Le</dc:creator>
      <pubDate>Tue, 03 Nov 2020 13:56:59 +0000</pubDate>
      <link>https://forem.com/codeprototype/learn-xamarin-forms-control-template-by-making-a-button-with-built-in-loading-indicator-in-4-steps-3lkm</link>
      <guid>https://forem.com/codeprototype/learn-xamarin-forms-control-template-by-making-a-button-with-built-in-loading-indicator-in-4-steps-3lkm</guid>
      <description>&lt;p&gt;In Xamarin.Forms, Control Template offers a powerful way to build a template. The template is built by composing smaller parts. But building a template is not the end goal. The end goal is to use a so-built template to make UI controls and use them anywhere without having to duplicate common codes.&lt;/p&gt;

&lt;p&gt;I’m going to show how to implement a button for a Xamarin.Forms app that has the following special features: (a) Upon being tapped-on, the button will show a loading indicator (Activity Indicator) indicating the app is doing some work asynchronously. (b) This button can be re-used every where in the application without any code duplication.&lt;/p&gt;

&lt;p&gt;As an example, the button, in normal state looks like:&lt;/p&gt;

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

&lt;p&gt;Upon being tapped-on, the button will show a loading indicator and looks like:&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;Side note: I came up with the prefix &lt;code&gt;AsyncButton&lt;/code&gt; to be used in the naming which might or might not be the best choice. But for the rest of this post, we’re stuck with it.&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 0. Read the official docs (optional)
&lt;/h4&gt;

&lt;p&gt;Read about Xamarin.Forms &lt;a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/control-template"&gt;Control Templates&lt;/a&gt; and &lt;a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/relative-bindings"&gt;Relative Binding&lt;/a&gt;. If it’s a little vague, hopefully, the docs are more valuable after the following 4 steps.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1. Create Bindable Properties in a View file
&lt;/h4&gt;

&lt;p&gt;Create a new file named &lt;code&gt;AsyncButtonView.cs&lt;/code&gt;(just a plain old &lt;code&gt;.cs&lt;/code&gt; file, no accompanying &lt;code&gt;.xaml&lt;/code&gt; file):&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Point of interest&lt;/strong&gt;: This class &lt;code&gt;AsyncButtonView&lt;/code&gt; subclasses from &lt;code&gt;ContentView&lt;/code&gt; and is really simple. It just lists all the bindable properties. Glancing at the variables names such &lt;code&gt;ButtonCornerRadius&lt;/code&gt;, &lt;code&gt;ButtonBackgroundColor&lt;/code&gt;, &lt;code&gt;ButtonTextColor&lt;/code&gt;, &lt;code&gt;ButtonText&lt;/code&gt;, etc, we can quickly tell that these properties are used later on to customize the look and feel of a button. But this class does not “blueprint” how to construct the button. That’s for step 2.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2. Build a Control Template for the Button
&lt;/h4&gt;

&lt;p&gt;A Control Template “blueprints” how to build the UI for the control. Create a new file named &lt;code&gt;AsyncButtonControlTemplateResourceDictionary.xaml&lt;/code&gt; and put it in the same folder with &lt;code&gt;App.xml&lt;/code&gt;(Every Xamarin.Forms app should already have an &lt;code&gt;App.xml&lt;/code&gt; file):&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Point of interest&lt;/strong&gt;: The Control Template above instructs to &lt;em&gt;build&lt;/em&gt; the button by composing smaller parts. It instructs to &lt;em&gt;layout&lt;/em&gt; a &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.button?view=xamarin-forms"&gt;Xamarin.Forms Button&lt;/a&gt; next to a &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.activityindicator?view=xamarin-forms"&gt;Xamarin.Forms ActivityIndicator&lt;/a&gt; horizontally (line 9 through 15). Then it instructs to put this layout inside a &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.frame?view=xamarin-forms"&gt;Xamarin.Forms Frame&lt;/a&gt; (line 5 through 16). This &lt;code&gt;Frame&lt;/code&gt; class allows for the Button’s rounded corners. Finally, we have a &lt;code&gt;Button ControlTemplate&lt;/code&gt; out this construction by wrapping it inside a &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.controltemplate?view=xamarin-forms"&gt;Xamarin.Forms ControlTemplate&lt;/a&gt; (line 4 through 17).&lt;/p&gt;

&lt;p&gt;But if you look more closely at this file, this &lt;code&gt;Button ControlTemplate&lt;/code&gt; is not connected to &lt;code&gt;AsyncButtonView&lt;/code&gt; in step 1 in any way. The connection will be made when this &lt;code&gt;Button ControlTemplate&lt;/code&gt; is actually used to make a button. All the bindings however are already specified by now as illustrated by the following line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BackgroundColor="{Binding Source={RelativeSource TemplatedParent},Path=ButtonBackgroundColor}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Step 3: Consume the Button ControlTemplate to make a button
&lt;/h4&gt;

&lt;p&gt;Finally we are ready to use the &lt;code&gt;Button ControlTemplate&lt;/code&gt; to make an Async Button. As an example, the following file shows how to put together everything that we have created so far:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Point of interest&lt;/strong&gt;: The file in step 2 &lt;code&gt;AsyncButtonControlTemplateResourceDictionary.xaml&lt;/code&gt; is referenced in the &lt;code&gt;ResourceDictionary&lt;/code&gt; on line 14. On line 20, the &lt;code&gt;AsyncButtonView&lt;/code&gt; and the &lt;code&gt;Button ControlTemplate&lt;/code&gt; work together along with the supplied values for the rest of the properties. These 2 lines (line 14 and line 20) “connects” the bindable properties in step 1 with the UI Control Template in step 2. Line 9 references the &lt;code&gt;ViewModel&lt;/code&gt; which we will do in step 4.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4: Add a ViewModel
&lt;/h4&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/khle"&gt;
        khle
      &lt;/a&gt; / &lt;a href="https://github.com/khle/AsyncButtonApp"&gt;
        AsyncButtonApp
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Cross posted on &lt;a href="https://kevinle.medium.com/learn-xamarin-forms-control-template-by-making-a-button-with-built-in-loading-indicator-in-4-steps-ac9142dc488"&gt;medium&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>xamarinforms</category>
    </item>
    <item>
      <title>Taking the Unhappy Path with Result, Option, unwrap and ? operator in Rust</title>
      <dc:creator>Kevin Le</dc:creator>
      <pubDate>Fri, 05 Jun 2020 21:52:29 +0000</pubDate>
      <link>https://forem.com/codeprototype/taking-the-unhappy-path-with-result-option-unwrap-and-operator-in-rust-482b</link>
      <guid>https://forem.com/codeprototype/taking-the-unhappy-path-with-result-option-unwrap-and-operator-in-rust-482b</guid>
      <description>&lt;p&gt;As I'm learning Rust, I noticed that these 4 concepts &lt;code&gt;Result&lt;/code&gt;, &lt;code&gt;Option&lt;/code&gt;, &lt;code&gt;unwrap&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt; are often discussed in conjunction with each other. In this post, I'd like to document and share the thought process I have been going through. This thought process has helped me understanding and how to be more idiomatic in Rust.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option
&lt;/h3&gt;

&lt;p&gt;Although Rust has a concept of &lt;a href="https://doc.rust-lang.org/std/ptr/fn.null.html"&gt;null&lt;/a&gt;, using null is not a common pattern in Rust. So let's say we have to write a function that, given the name of an mobile OS, the function will return the name of the store. If the string literal &lt;code&gt;iOS&lt;/code&gt; is passed as input to the function, it will return &lt;code&gt;App Store&lt;/code&gt;. If &lt;code&gt;android&lt;/code&gt;, then &lt;code&gt;Play Store&lt;/code&gt;.  Any other input is considered invalid. In most other languages, we can choose to return &lt;code&gt;null&lt;/code&gt; or a string literal &lt;code&gt;invalid&lt;/code&gt; or something like that. But doing so is not the Rust way.&lt;/p&gt;

&lt;p&gt;One idiomatic way in Rust to implement such function is to return an &lt;a href="https://doc.rust-lang.org/std/option/enum.Option.html"&gt;Option&lt;/a&gt;. An &lt;code&gt;Option&lt;/code&gt; or to be exact an &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt; is a &lt;code&gt;generic&lt;/code&gt; and can be either &lt;code&gt;Some&amp;lt;T&amp;gt;&lt;/code&gt; or &lt;code&gt;None&lt;/code&gt; (From here on, I will mostly drop the &lt;code&gt;generic type parameter T&lt;/code&gt; so the sentences do not get so cluttered).  Rust refers to 'Some' and 'None' as &lt;code&gt;variants&lt;/code&gt; (which does not have any equivalent in other languages, so I just don't get so hanged up on trying to define what a &lt;code&gt;variant&lt;/code&gt; is). In our example, in the &lt;code&gt;happy paths&lt;/code&gt;, the function returns the string literal "App Store" or "Play Store" wrapped in a &lt;code&gt;Some&lt;/code&gt; variant. In the &lt;code&gt;unhappy path&lt;/code&gt;, the function returns &lt;code&gt;None&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fn find_store(mobile_os: &amp;amp;str) -&amp;gt; Option&amp;lt;&amp;amp;str&amp;gt; {
    match mobile_os {
        "iOS" =&amp;gt; Some("App Store"),
        "android" =&amp;gt; Some("Play Store"),
        _ =&amp;gt; None
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;To consume &lt;code&gt;find_store()&lt;/code&gt;, we can call it as follow:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fn main() {
    println!("{}", match find_store("windows") {
        Some(s) =&amp;gt; s,
        None =&amp;gt; "Not a valid mobile OS"
    });
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You can try to run the above example in the &lt;a href="https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=21e4e13b2bf42d9342ef7ac7d4227c37"&gt;playground&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Result
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://doc.rust-lang.org/std/result/enum.Result.html"&gt;Result&lt;/a&gt; is related to &lt;code&gt;Option&lt;/code&gt; in Rust in that &lt;code&gt;Result&lt;/code&gt; or to be exact &lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;/code&gt; is a richer version of &lt;code&gt;Option&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;/code&gt; could have one of &lt;a href="https://doc.rust-lang.org/stable/rust-by-example/error/result.html"&gt;two outcomes&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Ok(T)&lt;/code&gt;: An element &lt;code&gt;T&lt;/code&gt; was found&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Err(E)&lt;/code&gt;: An error was found with element &lt;code&gt;E&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;as opposed to &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt; previously seen that can contains &lt;code&gt;Some&amp;lt;T&amp;gt;&lt;/code&gt; or &lt;code&gt;None&lt;/code&gt;. &lt;code&gt;Result&lt;/code&gt; has information about the error which is absent in &lt;code&gt;Option&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;Let's look at an example of a function that returns a &lt;code&gt;Result&lt;/code&gt;. This function is from the &lt;a href="https://docs.serde.rs/serde_json/de/fn.from_str.html"&gt;serde_json&lt;/a&gt; &lt;a href="https://crates.io/crates/serde_json"&gt;crate&lt;/a&gt; which is used to parse JSON. The signature of this function is&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pub fn from_str&amp;lt;'a, T&amp;gt;(s: &amp;amp;'a str) -&amp;gt; Result&amp;lt;T, Error&amp;gt; 
where
    T: Deserialize&amp;lt;'a&amp;gt;, 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Assume we want to parse the following &lt;code&gt;String&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let json_string = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;to a person object of this &lt;code&gt;struct&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    phones: Vec&amp;lt;String&amp;gt;,
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;the code that parses the &lt;code&gt;json_string&lt;/code&gt; to the &lt;code&gt;Person&lt;/code&gt; object is as follow:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let p:Person = match serde_json::from_str(json_string) {
    Ok(p) =&amp;gt; p,
    Err(e) =&amp;gt; ... //we will discuss what goes here next 
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The happy path is obvious. But let's say there's a typo in the input &lt;code&gt;json_string&lt;/code&gt;, &lt;code&gt;match&lt;/code&gt; will send the program flow to the &lt;code&gt;Err(e)&lt;/code&gt; clause. &lt;/p&gt;

&lt;p&gt;When the &lt;code&gt;Err&lt;/code&gt; is encountered, there are 2 actions that we can take:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;panic!&lt;/code&gt; (more about panic) &lt;a href="https://doc.rust-lang.org/book/ch09-01-unrecoverable-errors-with-panic.html"&gt;here&lt;/a&gt; and &lt;a href="https://doc.rust-lang.org/rust-by-example/std/panic.html"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;return&lt;/code&gt; the &lt;code&gt;Err&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Back to our example, here's the full code if we decide to &lt;code&gt;panic!&lt;/code&gt; &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=b2f48fe434cb589d6ece2c2d1e2cec39"&gt;Playground&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;or if we want to return &lt;code&gt;Err&lt;/code&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=66ef4c063f6437aaedb5f53fcc7d5bd5"&gt;Playground&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  unwrap
&lt;/h3&gt;

&lt;p&gt;In the above example, let's consider at the case where we decide to &lt;code&gt;panic!&lt;/code&gt;. The lines of code above&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let p: Person = match serde_json::from_str(data) {
        Ok(p) =&amp;gt; p,
        Err(e) =&amp;gt; panic!("cannot parse JSON {:?}, e"), //panic
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;is very verbose. Happy path is handled normally as expected, no discussion there. And when the &lt;code&gt;Err&lt;/code&gt; is encountered, the above code &lt;code&gt;panic!&lt;/code&gt;. We can replace the above verbose code with&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let p:Person = serde_json::from_str(data).unwrap();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;unwrap&lt;/code&gt; is OK to use if we know for sure that the input &lt;code&gt;json_string&lt;/code&gt; will always be parsable to the &lt;code&gt;Person&lt;/code&gt; struct, i.e. always happy path or if in case the &lt;code&gt;Err&lt;/code&gt; is encountered, the program can't go on and it's unrecoverable. During development, when we're more concerned with getting the general flow of the program, &lt;code&gt;unwrap&lt;/code&gt; can also be used as quick prototype.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;unwrap&lt;/code&gt; is implicit &lt;code&gt;panic!&lt;/code&gt;. Although there's no difference with the more verbose counterpart, the danger is it's implicit, so sometimes it's not really what really want to do.&lt;/p&gt;

&lt;p&gt;Regardless, if we need to call &lt;code&gt;panic!&lt;/code&gt;, the code is shown as below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=1d95f381008fb71dc95544be48f58a3e"&gt;Playground&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;?&lt;/code&gt; operator
&lt;/h3&gt;

&lt;p&gt;As opposed to &lt;code&gt;panic!&lt;/code&gt; when the &lt;code&gt;Err&lt;/code&gt; is encountered, we can &lt;code&gt;return&lt;/code&gt; the &lt;code&gt;Err&lt;/code&gt;. Not every &lt;code&gt;Err&lt;/code&gt; is unrecoverable, so there's no reason to &lt;code&gt;panic!&lt;/code&gt;. The verbose code to return &lt;code&gt;Err&lt;/code&gt; is shown again below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let p: Person = match serde_json::from_str(data) {
        Ok(p) =&amp;gt; p,
        Err(e) =&amp;gt; return Err(e.into()),
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;?&lt;/code&gt; offers us a more concise way to replace the verbose code above:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let p:Person = serde_json::from_str(data)?;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So the entire program is showm here&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=d99b3a46ae83b22938b87a637386c0c0"&gt;Playground&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Unpacking Option with unwrap and ?
&lt;/h3&gt;

&lt;p&gt;Just as we could use &lt;code&gt;unwrap&lt;/code&gt; and &lt;code&gt;?&lt;/code&gt; with &lt;code&gt;Result&lt;/code&gt;, we can also use &lt;code&gt;unwrap&lt;/code&gt; and &lt;code&gt;?&lt;/code&gt; with &lt;code&gt;Option&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If we &lt;code&gt;unwrap&lt;/code&gt; an &lt;code&gt;Option&lt;/code&gt; that has the underlying value of &lt;code&gt;None&lt;/code&gt;, the program &lt;code&gt;panic!&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here's an example of how to unwrap an &lt;code&gt;Option&lt;/code&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
&lt;a href="https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=ee3bdadbd11d2fbdcf3c84a0c8c87ee6"&gt;Playground&lt;/a&gt;

&lt;p&gt;Similarly, we can also unpack an &lt;code&gt;Option&lt;/code&gt; with the &lt;code&gt;?&lt;/code&gt; operator. If the outcome is &lt;code&gt;None&lt;/code&gt;, the program will terminate whatever function is being executed and return &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
    </item>
    <item>
      <title>Building an Eleventy site with PaperCSS</title>
      <dc:creator>Kevin Le</dc:creator>
      <pubDate>Mon, 13 Apr 2020 19:39:45 +0000</pubDate>
      <link>https://forem.com/codeprototype/building-an-eleventy-site-with-papercss-11dp</link>
      <guid>https://forem.com/codeprototype/building-an-eleventy-site-with-papercss-11dp</guid>
      <description>&lt;p&gt;&lt;em&gt;This was cross-posted on &lt;a href="https://khle.dev/blog/2020-04-09/"&gt;khle.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are many awesome static site generators and CSS frameworks. But none impresses me more than &lt;a href="https://www.11ty.dev"&gt;Eleventy&lt;/a&gt; and &lt;a href="https://www.getpapercss.com"&gt;PaperCSS&lt;/a&gt;. They are both simple and elegant, and together seem like a perfect combination.&lt;/p&gt;

&lt;p&gt;In just a few hours, even I could get this site up and running. This is my primary goal as I don't want to spend too much time on making a "blog website".&lt;/p&gt;

&lt;p&gt;To build one like this, just follow the following steps.&lt;/p&gt;

&lt;p&gt;From your Terminal or Console, install Eleventy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm install -g @11ty/eleventy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For my site, I want to have 3 areas: &lt;code&gt;blog&lt;/code&gt;, &lt;code&gt;about this site&lt;/code&gt; and &lt;code&gt;about me&lt;/code&gt;. So I'll make 3 folders:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir blog
$ mkdir about-site
$ mkdir about-me
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For this site, I decide to have 2 layouts. So let's create a folder and the layout files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir _includes
$ touch _includes/layout.njk
$ touch _includes/article-layout.njk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The main page which lists all the articles and the 2 "about" pages should follow 1 layout. The article pages should follow the other. These 2 layouts are similar as I could have get by with just one. You might not need both. Anyway, here's a link to the full content of&lt;br&gt;
&lt;a href="https://gist.github.com/khle/c0e2bda3a3b4b0bbc9e6e0469dd3cfcb"&gt;layout.njk&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now comes the fun part which is we get to write with &lt;code&gt;markdown&lt;/code&gt; syntax. Let's create the &lt;code&gt;about me&lt;/code&gt; page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ touch about-me/index.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and copy the following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
layout: layout.njk
pageTitle: About me
---

&amp;lt;article class="article"&amp;gt;
  &amp;lt;h1 class="article-title"&amp;gt;About me&amp;lt;/h1&amp;gt;
  &amp;lt;p class="text-lead"&amp;gt;Hi, put your intro here&amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;Lorem...&amp;lt;/p&amp;gt;
&amp;lt;/article&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next let's create the main page which is the page that lists all articles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch index.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and copy the following content to it.&lt;/p&gt;

&lt;p&gt;The first line above allows my articles to be listed in reverse chronological order.&lt;/p&gt;

&lt;p&gt;Finally, to organize my blog articles in the file system, I keep them in sub-folders under the &lt;code&gt;blog&lt;/code&gt; folder that was created earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd blog
$ mkdir 2020-04-09
$ cd ..
$ touch blog/2020-04-09/index.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and start writing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
layout: article-layout.njk
title: Building an Eleventy site with PaperCSS
date: 2020-04-09
tags: post
---
##### Published on {{ date | date : '%Y-%m-%d' }}
#### {{ title }}
###### `Eleventy`, `PaperCSS`
Lorem...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;p&gt;Some tips:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Table&lt;br&gt;
You can use &lt;a href="https://www.markdownguide.org/extended-syntax/"&gt;markdown extended syntax&lt;/a&gt; to embed tables in your content. There is this &lt;a href="https://www.tablesgenerator.com/markdown_tables"&gt;handy tool&lt;/a&gt; to help out.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you need to have buttons to perform some actions we can use the following snippets:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="row"&amp;gt;
    &amp;lt;button class="article-meta"&amp;gt;&amp;lt;a href="#"&amp;gt;Do something&amp;lt;/a&amp;gt;&amp;lt;/button&amp;gt;
    &amp;lt;button class="article-meta"&amp;gt;Do something else&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;which results in &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button class="article-meta"&amp;gt;&amp;lt;a href="#"&amp;gt;Do something&amp;lt;/a&amp;gt;&amp;lt;/button&amp;gt;
&amp;lt;button class="article-meta"&amp;gt;Do something else&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

</description>
      <category>eleventy</category>
      <category>papercss</category>
    </item>
    <item>
      <title>Configuring both CSS Modules and global CSS for ReactJS in Webpack</title>
      <dc:creator>Kevin Le</dc:creator>
      <pubDate>Tue, 07 Apr 2020 19:04:25 +0000</pubDate>
      <link>https://forem.com/codeprototype/configuring-both-css-modules-and-global-css-for-reactjs-in-webpack-4ci7</link>
      <guid>https://forem.com/codeprototype/configuring-both-css-modules-and-global-css-for-reactjs-in-webpack-4ci7</guid>
      <description>&lt;p&gt;I prefer to keep all common CSS style rules in a global CSS style, called &lt;code&gt;app.css&lt;/code&gt; for example. For style rules that only pertain to a particular component, then I'd like to keep in a separate CSS module. However, I want to be able to use the same &lt;code&gt;className&lt;/code&gt; everywhere. For example, I might have a &lt;code&gt;.logo&lt;/code&gt; class that are used everywhere, but my &lt;code&gt;Header&lt;/code&gt; component needs a different logo. In this case, I might want to use both global CSS and CSS modules. This is a simple concept but the tricky part is in the details which is the Webpack configuration &lt;code&gt;webpack.config.js&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.logo&lt;/code&gt; class is defined in the global &lt;code&gt;app.css&lt;/code&gt; as follow:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  1. CSS module naming requirement
&lt;/h4&gt;

&lt;p&gt;For the &lt;code&gt;Header&lt;/code&gt; component, Webpack dictates that the CSS module has to be named according to the pattern &lt;code&gt;something.module.css&lt;/code&gt;. So in this example, I will name it &lt;code&gt;header.module.css&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Name mangling
&lt;/h4&gt;

&lt;p&gt;The .logo is defined in the &lt;code&gt;header.module.css&lt;/code&gt; as follow:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;To differentiate the two &lt;code&gt;.logo&lt;/code&gt; classNames, Webpack does the heavy lifting. It mangles the className &lt;code&gt;.logo&lt;/code&gt; in &lt;code&gt;header.module.css&lt;/code&gt;. If we look at the page source, we will see something like &lt;code&gt;_app_header_module_css__WEBPACK_IMPORTED_MODULE_2___default.a.logo&lt;/code&gt; as opposed to simply &lt;code&gt;logo&lt;/code&gt; in &lt;code&gt;app.css&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. webpack.config.js
&lt;/h4&gt;

&lt;p&gt;We don't care about the above heavy lifting that Webpack does, but we have to abide by its requirement. We will need to configure 2 different rules: one for the global CSS and another for CSS module. &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The first rule is for CSS module and second is for global CSS. You can easily tell by looking at the &lt;code&gt;include&lt;/code&gt; key in each rule.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Outdated information
&lt;/h4&gt;

&lt;p&gt;You might have seen some older posts which showed outdated information:&lt;/p&gt;

&lt;p&gt;For example,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test: /\.css$/,
  loader: 'style!css-loader?modules&amp;amp;importLoaders=1&amp;amp;localIdentName=[name]__[local]___[hash:base64:5]'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    test: /\.(css|scss)$/,
    use: [
      'style-loader',
      {
        loader: 'css-loader',
        options: {
          modules: true,
          importLoaders: 1,
          localIdentName: '[name]__[local]__[hash:base64:5]'
        }
      }
    ],
    include: /\.module\.css$/
},
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;These will break the Webpack compiling &lt;code&gt;npm run webpack&lt;/code&gt;. Don't use them.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Consume CSS style rules in ReactJS
&lt;/h4&gt;

&lt;p&gt;Write the code for ReactJS is the easiest part:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//from global CSS
import './app.css'

return (
   &amp;lt;div&amp;gt;
      &amp;lt;div className='logo' /&amp;gt;
   &amp;lt;/div&amp;gt;
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//from CSS Module
import styles from "./header.module.css"

return (
   &amp;lt;div&amp;gt;
      &amp;lt;div className={styles.logo} /&amp;gt;
   &amp;lt;/div&amp;gt;
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



</description>
      <category>react</category>
      <category>webpack</category>
      <category>cssmodules</category>
    </item>
    <item>
      <title>Accelerating to delivery: Quickly build an Admin Panel or Dashboard-like app using ReactJS, Tailwind CSS. Part I </title>
      <dc:creator>Kevin Le</dc:creator>
      <pubDate>Fri, 03 Apr 2020 00:06:16 +0000</pubDate>
      <link>https://forem.com/codeprototype/accelerating-to-delivery-quickly-build-an-admin-panel-or-dashboard-like-app-using-reactjs-tailwind-css-part-i-fd1</link>
      <guid>https://forem.com/codeprototype/accelerating-to-delivery-quickly-build-an-admin-panel-or-dashboard-like-app-using-reactjs-tailwind-css-part-i-fd1</guid>
      <description>&lt;p&gt;Building a ReactJS app is like building with LEGO blocks. We build larger components out of smaller components and keep repeating that until we have something like the LEGO structure in the above image (Photo by Alphacolor on Unsplash) or an Admin Panel/Dashboard-like UI below: &lt;/p&gt;

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

&lt;p&gt;To do quickly, we will use the &lt;a href="https://github.com/tailwindadmin/admin"&gt;Admin Panel template built on Tailwind CSS&lt;/a&gt; by &lt;a href="https://github.com/tailwindadmin"&gt;tailwindadmin&lt;/a&gt;. Instead of taking the traditional approach like those &lt;code&gt;Counter&lt;/code&gt; or &lt;code&gt;Todo&lt;/code&gt; tutorials, we will get this application, just like what you see above, up and running first. At first, everything is in 1 big JS file that contain 1 big ReactJS component. Then in part II, we will refactor by breaking it up into smaller components.&lt;/p&gt;

&lt;p&gt;This is my preferred approach as I believe it allows me to get to delivery a lot quicker. Our real app will look a lot like this kind of Admin Panel rather than a counter that has 2 buttons and a label. We will be able to easily derive from what we have here.&lt;/p&gt;

&lt;p&gt;Launch a terminal or console and start typing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init -y
npm i --save-dev webpack webpack-cli path
npm i --save-dev @babel/core @babel/node 
npm i --save-dev @babel/preset-env @babel/preset-react 
npm i --save-dev @babel/plugin-proposal-class-properties babel-loader
npm i --save-dev css-loader 
npm i --save-dev postcss-loader autoprefixer 
npm i --save-dev html-webpack-plugin
npm i --save-dev mini-css-extract-plugin postcss-loader
npm i --save-dev @fullhuman/postcss-purgecss postcss-import
npm i --save tailwindcss tailwindcss-tables
npm i --save react react-dom
npm i --save express webpack-dev-middleware
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then make a new directory called &lt;code&gt;client&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We will create some empty files, just place holders first. We will copy contents to them later. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;I will use the &lt;code&gt;touch&lt;/code&gt; command. If you're on Windows and the command &lt;code&gt;touch&lt;/code&gt; is not available, use the PowerShell alternative command &lt;code&gt;New-Item&lt;/code&gt;. Or use whatever way you prefer to create an empty file with each of those filenames.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's create 3 files in this &lt;code&gt;client&lt;/code&gt; directory. Remember they will be empty at first, but we will copy contents to them later:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch client/index.html
touch client/index.js
touch client/style.css
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Create a file on the server side for NodeJS:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch server.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Finally create the following &lt;code&gt;config&lt;/code&gt; files:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;touch webpack.config.js
touch .babelrc
touch postcss.config.js
npx tailwind init tailwind.config.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Regardless of how you created those empty files, copy the contents listed at the end of the post to each of them.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;package.json&lt;/code&gt; file, find the &lt;code&gt;"scripts"&lt;/code&gt; key and replace with the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
    "test": "echo \"Error: no test specified\" &amp;amp;&amp;amp; exit 1",
    "webpack": "babel-node ./node_modules/webpack/bin/webpack",
    "start": "node server.js"
},
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;After you copy the file contents, &lt;code&gt;webpack build&lt;/code&gt; it and run:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run webpack
npm start
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You should see a nice Admin Panel ReactJS application.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;




&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


</description>
      <category>react</category>
      <category>webpack</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>How to understand AWS, Azure, Firestore Cloud, etc pricing?</title>
      <dc:creator>Kevin Le</dc:creator>
      <pubDate>Tue, 11 Feb 2020 23:18:49 +0000</pubDate>
      <link>https://forem.com/codeprototype/how-to-understand-aws-azure-firestore-cloud-etc-pricing-57n1</link>
      <guid>https://forem.com/codeprototype/how-to-understand-aws-azure-firestore-cloud-etc-pricing-57n1</guid>
      <description>&lt;p&gt;I found none of the pricing descriptions is clear. The calculators are not helpful either. What can help? Do you have a cheat sheet? &lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>Accessing application settings from Azure Function Apps in a Docker Container</title>
      <dc:creator>Kevin Le</dc:creator>
      <pubDate>Thu, 12 Dec 2019 20:25:15 +0000</pubDate>
      <link>https://forem.com/codeprototype/accessing-application-settings-from-azure-function-apps-in-a-docker-container-1fjg</link>
      <guid>https://forem.com/codeprototype/accessing-application-settings-from-azure-function-apps-in-a-docker-container-1fjg</guid>
      <description>&lt;h3&gt;
  
  
  Abstract
&lt;/h3&gt;

&lt;p&gt;In my &lt;a href="https://dev.to/codeprototype/azure-function-app-and-docker-on-azure-made-easy-in-12-steps-3fob"&gt;previous article&lt;/a&gt;, the business logic in the Function App is practically none.  But one of the first common things of all software programs, Azure Function Apps or otherwise, in a real-world scenario is reading &lt;code&gt;environment variables&lt;/code&gt;. In this article, I will refer to these &lt;code&gt;environment variables&lt;/code&gt; as &lt;code&gt;application settings&lt;/code&gt;. The reason is that I don't want us to get mixed up with &lt;code&gt;environment variables&lt;/code&gt; that are &lt;a href="https://docs.docker.com/engine/reference/commandline/run/"&gt;passed to the Docker container&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Application settings in this context are, for example, the Function App needs to read the API key and/or secret of a third-party service in order to query for some data. Another example might be the connection string of the database. Generally, it is considered a bad programming to hard-code these values in the code itself. Since these values are configurable data, they should be decoupled from the program code and should live in an &lt;code&gt;environment variable&lt;/code&gt; file or something like that. The key concept here is they should be decoupled.&lt;/p&gt;

&lt;p&gt;The goal is we want to allow Function Apps to read application settings so that they can run locally and run inside a Docker container on the Desktop, as well as on Azure, inside and outside of an Azure Docker container.     &lt;/p&gt;

&lt;h3&gt;
  
  
  Review: Non Docker way
&lt;/h3&gt;

&lt;p&gt;Forget about Docker for a moment, let's say we write the Azure Function App on our development computer, we can keep all &lt;code&gt;application settings&lt;/code&gt; in a file named &lt;code&gt;local.settings.json&lt;/code&gt;. This file is in JSON format, and looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "SomeAPIClientKey": "...",
    "SomeAPIClientSecret": "..."
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The function can access these application settings and be written as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[FunctionName("kleSampleFunc")]
public static async Task&amp;lt;IActionResult&amp;gt; Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log, ExecutionContext context)
    {
        var configuration = new ConfigurationBuilder()
            .SetBasePath(context.FunctionAppDirectory)                    
            .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables()
            .Build();

        var apiKey = configuration["SomeAPIClientKey"];
        var apiSecret = configuration["SomeAPIClientSecret"];
        log.LogInformation($"apiKey: {apiKey}");
        log.LogInformation($"apiSecret : {apiSecret}");

        // .... Business logic that makes use of apiKey and apiSecret

        return OkObjectResult(new {
            //whatever        
        });         
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can run it locally using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ func start --build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We might choose NOT to commit the file &lt;code&gt;local.settings.json&lt;/code&gt; to Source Control, so it won't get deployed. But it doesn't matter because when this Function App runs on Azure, the &lt;code&gt;environment variables&lt;/code&gt; are no longer coming from the file &lt;code&gt;local.settings.json&lt;/code&gt;. Instead, there's an Application Settings blade on Azure Portal where we can configure them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker
&lt;/h3&gt;

&lt;p&gt;From my previous &lt;a href="https://dev.to/codeprototype/azure-function-app-and-docker-on-azure-made-easy-in-12-steps-3fob"&gt;article&lt;/a&gt;, the Function App running in the local Docker Desktop will not be able to read any &lt;code&gt;environment variable&lt;/code&gt; from the &lt;code&gt;local.settings.json&lt;/code&gt; file. &lt;/p&gt;

&lt;p&gt;Assume we already run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker build -t kle/sampledockerimg .
$ docker run -p 7071:80 kle/sampledockerimg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Test from Postman or &lt;code&gt;curl&lt;/code&gt;, you will see the 2 &lt;code&gt;log.LogInformation()&lt;/code&gt; statements above outputting &lt;code&gt;null&lt;/code&gt; values for &lt;code&gt;apiKey&lt;/code&gt; and &lt;code&gt;apiSecret&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So launch another Terminal or Console, and run this command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker ps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You will see the output in tabular format with 7 columns. The last column is &lt;code&gt;NAMES&lt;/code&gt;. Note the value of this column for the docker image of your Function App. It's some kind of made-up name and varies each time the image is rebuilt. For example, I see mine as &lt;code&gt;vigorous_bhaskara&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So now run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker exec -it vigorous_bhaskara /bin/bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The command above allows us accessing the file system, similar to SSH.&lt;/p&gt;

&lt;p&gt;So if you run the linux &lt;code&gt;ls&lt;/code&gt; command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ls /home/site/wwwroot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You will NOT see the file &lt;code&gt;local.settings.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So if the file containing the &lt;code&gt;environment variables&lt;/code&gt; is not present, how can can anything read their values? The fix is simple. All we have to do is copying the file to Docker container using the Docker copy command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker cp local.settings.json 16527b513905:/home/site/wwwroot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Run Postman or &lt;code&gt;curl&lt;/code&gt; again, everything should work. &lt;/p&gt;

&lt;p&gt;On the other hand, the same Function App, deployed to Azure, will be able to read all &lt;code&gt;environment variables&lt;/code&gt; that have been configured in the Application Settings blade on Azure Portal. So we don't have to do anything there. &lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Long story short, just remember these 3 commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker ps
$ docker exec -it vigorous_bhaskara /bin/bash
$ docker cp local.settings.json 16527b513905:/home/site/wwwroot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The first command tells us the container name and container id. In the example, that's &lt;code&gt;vigorous_bhaskara&lt;/code&gt; and &lt;code&gt;16527b513905&lt;/code&gt; respectively.&lt;/p&gt;

&lt;p&gt;The second one allows us to access the file system of the Docker Container, in an SSH-like way.&lt;/p&gt;

&lt;p&gt;The third one copies  the &lt;code&gt;local.settings.json&lt;/code&gt; from the host computer to the container.&lt;/p&gt;

</description>
      <category>azurefunctionapp</category>
      <category>docker</category>
      <category>azure</category>
    </item>
  </channel>
</rss>
