<?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: Remi Kristelijn</title>
    <description>The latest articles on Forem by Remi Kristelijn (@rkristelijn).</description>
    <link>https://forem.com/rkristelijn</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%2F182894%2Fd4890451-30f2-4eb5-916e-c91b90c40828.jpeg</url>
      <title>Forem: Remi Kristelijn</title>
      <link>https://forem.com/rkristelijn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rkristelijn"/>
    <language>en</language>
    <item>
      <title>Conventional Messaging</title>
      <dc:creator>Remi Kristelijn</dc:creator>
      <pubDate>Wed, 26 Feb 2025 12:46:59 +0000</pubDate>
      <link>https://forem.com/rkristelijn/conventional-messaging-2jdp</link>
      <guid>https://forem.com/rkristelijn/conventional-messaging-2jdp</guid>
      <description>&lt;p&gt;With remote work and on-the-go messaging, frustration can arise quickly. Sometimes, even small conventions—ones you might not even be aware of—can trigger irritation. For example, ending a short message with a dot (.) is now often interpreted as “end of discussion.”&lt;/p&gt;

&lt;p&gt;To create clarity and a shared understanding, I’ve compiled a list of messaging do’s and don’ts. This project is open for discussion and contributions via pull requests.&lt;/p&gt;

&lt;p&gt;I'm certain there is a lot missing still, please get involved and create an issue or even a PR. I'm also happy with a translation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rkristelijn/conventional-messaging" rel="noopener noreferrer"&gt;Conventional Messaging&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>devdiscuss</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Easy switching git projects</title>
      <dc:creator>Remi Kristelijn</dc:creator>
      <pubDate>Wed, 06 Nov 2024 07:11:17 +0000</pubDate>
      <link>https://forem.com/rkristelijn/easy-switching-git-projects-381p</link>
      <guid>https://forem.com/rkristelijn/easy-switching-git-projects-381p</guid>
      <description>&lt;p&gt;If you are working a lot of git projects, like maintaining things, having to bump versions, doing &lt;code&gt;npm outdated&lt;/code&gt; or &lt;code&gt;npm upgrade&lt;/code&gt;, maybe you want to quickly see what node version it runs in, as this needs to change two times a year. &lt;/p&gt;

&lt;p&gt;Probably you have one folder on your machine containing all your projects, maybe even nested in groups. But do you remember each path and do you like typing and cd'ing into them? I'm sure it gets annoying at some time, at least that's what happened to me.&lt;/p&gt;

&lt;p&gt;I started using aliasses in &lt;code&gt;.zshrc&lt;/code&gt; to quickly cd into them however the amount of projects kept growing. There must be some way to list them, because they all have a &lt;code&gt;.git&lt;/code&gt; folder in them. So I created Lcode.&lt;/p&gt;

&lt;p&gt;Lcode lists your repos in a specific folder (the root folder of your projects). After choosing, it changes directory for that folder and you can configure to run your favorite command, or just start &lt;code&gt;bash&lt;/code&gt; or &lt;code&gt;zsh&lt;/code&gt;, or even fire up Visual Studio Code. &lt;/p&gt;

&lt;p&gt;In my example below the 'command' in the config file checks for the existence of a &lt;code&gt;.nvmrc&lt;/code&gt; file and it it exists, runs nvm to switch to the proper node version for that project.&lt;/p&gt;

&lt;p&gt;You can either use the defaults, add command arguments or generate a config file to persist them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Frkristelijn%2Flcode%2Fblob%2FHEAD%2Fdocs%2Fdemo.gif%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Frkristelijn%2Flcode%2Fblob%2FHEAD%2Fdocs%2Fdemo.gif%3Fraw%3Dtrue" width="652" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/@rkristelijn/lcode" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@rkristelijn/lcode&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>node</category>
      <category>sideprojects</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I can get away with never installing npm packages globally</title>
      <dc:creator>Remi Kristelijn</dc:creator>
      <pubDate>Wed, 29 May 2024 06:54:57 +0000</pubDate>
      <link>https://forem.com/rkristelijn/how-i-can-get-away-with-never-installing-npm-packages-globally-2o6o</link>
      <guid>https://forem.com/rkristelijn/how-i-can-get-away-with-never-installing-npm-packages-globally-2o6o</guid>
      <description>&lt;p&gt;My belief is that when you clone a git repository all code, settings and tools should be contained in that cloned repo; the directory. It should not contaminate the system, not by tools, not by environment variables, maybe a bit for the platform. &lt;/p&gt;

&lt;h1&gt;
  
  
  Scope
&lt;/h1&gt;

&lt;p&gt;This article will not discuss the use of &lt;code&gt;.env&lt;/code&gt; file for maintaining environment variables or the &lt;code&gt;.nvmrc&lt;/code&gt; to enable automatically switching to the proper node version. Also it will not include info about &lt;code&gt;.npmrc&lt;/code&gt; file to e.g. lock the node version.&lt;/p&gt;

&lt;h1&gt;
  
  
  Trigger to write this article
&lt;/h1&gt;

&lt;p&gt;So many README.md files or manuals say things like:&lt;/p&gt;

&lt;p&gt;// &lt;a href="https://angular.io/guide/setup-local"&gt;https://angular.io/guide/setup-local&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @angular/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More candidates like these are, but not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;eslint&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prettier&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;create-react-app&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;webpack&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@vue/cli&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nx&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why would you want to do this? You have now local packages to maintain, and you can't use it across different projects that may have different versions of that software package. &lt;/p&gt;

&lt;h2&gt;
  
  
  Enter &lt;code&gt;npx&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;npx is a package runner tool that comes with &lt;code&gt;npm 5.2.0&lt;/code&gt; and higher. The current version when writing this article is &lt;code&gt;npm 10.8.0&lt;/code&gt; It is designed to execute binaries from Node packages without globally installing them. However, NPM documentation suggests globally installing certain packages, especially when they are CLI tools that will be used frequently across different projects.&lt;/p&gt;

&lt;p&gt;So instead of installing globally you can execute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @angular/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or even if you want to use a specific version of &lt;a href="https://www.npmjs.com/package/@angular/cli"&gt;@angular/cli&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @angular/cli@17 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have to type less, you can specify exact versions and you don't contaminate the developer's machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  But what about &lt;code&gt;package.json&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;package.json&lt;/code&gt; file serves as the cornerstone of any Node.js project, acting as the project's manifest. It provides critical metadata such as the project’s name, version, and author, and it specifies the dependencies and devDependencies required for the project to run and be developed. Additionally, &lt;code&gt;package.json&lt;/code&gt; defines custom scripts that automate common tasks like building, testing, and starting the application. This file ensures consistent environment setup, simplifies dependency management, and facilitates project configuration, making it an essential tool for maintaining and sharing Node.js projects.&lt;/p&gt;

&lt;p&gt;So if it is a dependency of the project, why not add it to the &lt;code&gt;dependencies&lt;/code&gt;, &lt;code&gt;devDependencies&lt;/code&gt; or even &lt;code&gt;peerDependencies&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;You can specify the exact versions, using carot-minor (^) or tilde-patch (~) imports. It even automatically updates when fixes arrives. &lt;/p&gt;

&lt;h2&gt;
  
  
  But I can't run the tools' commands directly from the shell?
&lt;/h2&gt;

&lt;p&gt;Well, fair point. If you want to run e.g. eslint, you don't want to enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node_modules/eslint/bin/eslint.js &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;enter &lt;code&gt;npm&lt;/code&gt; &lt;code&gt;scripts&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;You can simply write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint ."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So why does this work?&lt;/p&gt;

&lt;p&gt;NPM scripts can locate executables in the project's node_modules/.bin directory without needing to specify the full path. I does also look at the project itself and the global installed packages and eventually just performs the command hoping the OS will pick it up. &lt;/p&gt;

&lt;p&gt;So that does mean that you can also install e.g. &lt;code&gt;nx&lt;/code&gt; and use a script to alias the &lt;code&gt;nx&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nx"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  But what about passing arguments?
&lt;/h2&gt;

&lt;p&gt;You can't simply pass arguments to &lt;code&gt;nx&lt;/code&gt; as &lt;code&gt;nx --help&lt;/code&gt;, you need to pass them as positional arguments using an extra pair of dashes &lt;code&gt;--&lt;/code&gt; like so as described in the &lt;a href="https://docs.npmjs.com/cli/v10/commands/npm-run-script#:~:text=Any%20positional%20arguments%20are%20passed%20to%20the%20specified%20script.%20Use%20%2D%2D%20to%20pass%20%2D%2Dprefixed%20flags%20and%20options%20which%20would%20otherwise%20be%20parsed%20by%20npm."&gt;npm documentation&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nx &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So that is why I don't need to install any global dependency. Ever. Because we have &lt;code&gt;npx&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt; &lt;code&gt;scripts&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>npm</category>
      <category>scripts</category>
      <category>global</category>
      <category>dependencies</category>
    </item>
    <item>
      <title>WIP: Node development on iPhone or iPad</title>
      <dc:creator>Remi Kristelijn</dc:creator>
      <pubDate>Fri, 19 Apr 2024 09:26:42 +0000</pubDate>
      <link>https://forem.com/rkristelijn/node-development-on-iphone-3b5h</link>
      <guid>https://forem.com/rkristelijn/node-development-on-iphone-3b5h</guid>
      <description>&lt;h2&gt;
  
  
  Objective
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;work on Node/React projects on the go with an external keyboard with native iPad or iPhone. Not a web solution but from the shell.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Update
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;this is just a dump of my commands and findings. It is not stable yet, still finding out things... keep you posted&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Update 20240726 - i Switched to iPad pro because iPhone 11 pro can’t use side-by side and when the console is not in focus, the website that I serve doesn’t respond and I have to alt-tab and alt-tab back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why even want this?
&lt;/h2&gt;

&lt;p&gt;Just for fun, because I can. Practise with shell, if you have shell, you can do everything (except browsing the web for pages that use javascript).&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;only &lt;code&gt;vi&lt;/code&gt; seems to be stable, nvim &lt;/li&gt;
&lt;li&gt;without side-by-side the server process halts when out of focus&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How (basics)
&lt;/h2&gt;

&lt;p&gt;install ish from app store&lt;/p&gt;

&lt;p&gt;&lt;code&gt;~ uname -a&lt;br&gt;
Linux iPad 4.20.69-ish SUPER AWESOME May 20 2023 23:41:32 i686 Linux&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ish-app/ish/wiki/FAQ" rel="noopener noreferrer"&gt;iSH FAQ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pkgs.alpinelinux.org/packages" rel="noopener noreferrer"&gt;find packages to install&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  To find out still
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;where are the logs&lt;/li&gt;
&lt;li&gt;how to debug? nvim keeps on crashing, nothing in /var/log&lt;/li&gt;
&lt;li&gt;how to scroll up with keyboard?&lt;/li&gt;
&lt;li&gt;can I use it for web development?&lt;/li&gt;
&lt;li&gt;how to restore fast after reset?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Q&amp;amp;A
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;how to reset to clean ish? Yes: remove the app, reinstall&lt;/li&gt;
&lt;li&gt;is it persistant? Yes: after restart, it keeps the installed packages and your code&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Alpine Package Keeper (apk)
&lt;/h2&gt;

&lt;p&gt;apk add git&lt;br&gt;
apk search nodejs-current&lt;/p&gt;
&lt;h2&gt;
  
  
  Editor: neovim
&lt;/h2&gt;

&lt;p&gt;Don't use, not stable (at least not edge), will try&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo https://dl-cdn.alpinelinux.org/alpine/edge/main &amp;gt; /etc/apk/repositories
echo https://dl-cdn.alpinelinux.org/alpine/edge/community &amp;gt;&amp;gt; /etc/apk/repositories
apk update
apk upgrade
apk add neovim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/craftzdog/how-to-use-neovim-0-5-on-ish-on-ipados-2ie5"&gt;source&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;not all commands work: vsplit etc, keeps on crashing&lt;/p&gt;

&lt;p&gt;nvim&lt;br&gt;
escape key: ctrl-c&lt;br&gt;
&lt;a href="https://dev.to/arafat4693/basic-neovim-commands-4hmi"&gt;basic noevim commands&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Shell
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=CF1tMjvHDRA&amp;amp;ab_channel=JoseanMartinez" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=CF1tMjvHDRA&amp;amp;ab_channel=JoseanMartinez&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;apk add curl&lt;/code&gt;&lt;br&gt;
&lt;code&gt;apk add zsh&lt;/code&gt;&lt;br&gt;
&lt;code&gt;apk add git&lt;/code&gt;&lt;br&gt;
&lt;code&gt;sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Node
&lt;/h2&gt;

&lt;p&gt;If you install npm and nodejs-current then you get v16.11.1 and npm 7.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜  ~ apk search node npm
npm-7.17.0-r0
nodejs-less-4.1.1-r0
nodejs-14.21.3-r0
npm-doc-7.17.0-r0
nodejs-clean-css-5.1.2-r0
nodejs-current-doc-16.11.1-r0
nodejs-current-16.11.1-r0
nodejs-dev-14.21.3-r0
nodejs-current-dev-16.11.1-r0
npm-bash-completion-7.17.0-r0
nodejs-doc-14.21.3-r0
➜  ~ 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install node:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apk add nodejs-current npm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;latest is v14, v16 is there as 'current'&lt;br&gt;
See &lt;a href="https://dl-cdn.alpinelinux.org/alpine/" rel="noopener noreferrer"&gt;https://dl-cdn.alpinelinux.org/alpine/&lt;/a&gt; for latest or specific version&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;vi /etc/apk/repositories&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tried, but doesn’t work:a``&lt;br&gt;
add:&lt;br&gt;
&lt;a href="https://dl-cdn.alpinelinux.org/alpine/latests-stable/main" rel="noopener noreferrer"&gt;https://dl-cdn.alpinelinux.org/alpine/latests-stable/main&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dl-cdn.alpinelinux.org/alpine/latest-stable/community" rel="noopener noreferrer"&gt;https://dl-cdn.alpinelinux.org/alpine/latest-stable/community&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;apk upgrade&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;// need specific version because npm has newer versions&lt;/p&gt;

&lt;p&gt;apk add node npm&lt;/p&gt;

&lt;h2&gt;
  
  
  SSH
&lt;/h2&gt;

&lt;p&gt;// todo&lt;/p&gt;

&lt;h2&gt;
  
  
  Update the shell
&lt;/h2&gt;

&lt;p&gt;// todo&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample web project
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mkdir -p ~/git/hub/express-test &amp;amp;&amp;amp; cd "$_"&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git init -q&lt;/code&gt; - generate a &lt;code&gt;.git&lt;/code&gt; folder&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm init -y&lt;/code&gt; - init a default &lt;code&gt;package.json&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm i&lt;/code&gt; - init the node_modules folder&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm i express&lt;/code&gt; - &lt;/li&gt;
&lt;li&gt;&lt;code&gt;mkdir -p src &amp;amp;&amp;amp; touch $_/index.js&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;js&lt;br&gt;
const express = require('express')&lt;br&gt;
const app = express()&lt;br&gt;
const port = 3000&lt;/p&gt;

&lt;p&gt;app.get('/', (req, res) =&amp;gt; {&lt;br&gt;
  res.send('Hello World!')&lt;br&gt;
})&lt;/p&gt;

&lt;p&gt;app.listen(port, () =&amp;gt; {&lt;br&gt;
  console.log(&lt;code&gt;Example app listening on port ${port}&lt;/code&gt;)&lt;br&gt;
})&lt;br&gt;
&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/craftzdog/how-to-use-neovim-0-5-on-ish-on-ipados-2ie5"&gt;Install neovim on ish&lt;/a&gt;
&lt;a href="https://dev.to/arafat4693/basic-neovim-commands-4hmi"&gt;basic neovim commands&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Most elemental code formatting for Typescript/Javascript: .editorconfig vs prettier</title>
      <dc:creator>Remi Kristelijn</dc:creator>
      <pubDate>Thu, 18 Apr 2024 06:10:43 +0000</pubDate>
      <link>https://forem.com/rkristelijn/most-basic-code-formatting-3cmb</link>
      <guid>https://forem.com/rkristelijn/most-basic-code-formatting-3cmb</guid>
      <description>&lt;h1&gt;
  
  
  Context
&lt;/h1&gt;

&lt;p&gt;When working on Javascript/Typescript projects probably most of us know the following;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://eslint.org/"&gt;eslint&lt;/a&gt; is used to avoid code errors&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://prettier.io/"&gt;prettier&lt;/a&gt; is used to format you text&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Enter editorconfig
&lt;/h1&gt;

&lt;p&gt;These are tools that you need to add. But the most elemental code formatting is not here, it is in the widely supported &lt;a href="https://editorconfig.org/"&gt;.editorconfig&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;You can generate such a file with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx editorconfig-cli init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is basically an &lt;code&gt;ini&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;root&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;

&lt;span class="nn"&gt;[*]&lt;/span&gt;
&lt;span class="py"&gt;charset&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;utf-8&lt;/span&gt;
&lt;span class="py"&gt;indent_style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;space&lt;/span&gt;
&lt;span class="py"&gt;indent_size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;2&lt;/span&gt;
&lt;span class="py"&gt;end_of_line&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;lf&lt;/span&gt;
&lt;span class="py"&gt;trim_trailing_whitespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;insert_final_newline&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;max_line_length&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;100&lt;/span&gt;
&lt;span class="py"&gt;quote_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;single&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The best thing is that your code editor or IDE will recognise this file automatically and formats your code per this &lt;code&gt;.editorconfig&lt;/code&gt; file by default, or there is a plugin. &lt;/p&gt;

&lt;h1&gt;
  
  
  IDE support for prettier and editorconfig
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Visual Studio Code (VSC) uses a &lt;a href="https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig"&gt;plugin&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Vim uses a &lt;a href="https://github.com/editorconfig/editorconfig-vim"&gt;plugin&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Nvim supports this by &lt;a href="https://neovim.io/doc/user/editorconfig.html"&gt;default&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;IntelliJ IDEA uses a &lt;a href="https://www.jetbrains.com/help/idea/editorconfig.html"&gt;plugin&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sublime uses a &lt;a href="https://packagecontrol.io/packages/EditorConfig"&gt;plugin&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Atom uses a &lt;a href="https://github.com/sindresorhus/atom-editorconfig"&gt;plugin&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In table format:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Editor/IDE&lt;/th&gt;
&lt;th&gt;Prettier Support&lt;/th&gt;
&lt;th&gt;.editorconfig Support&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Visual Studio Code&lt;/td&gt;
&lt;td&gt;✅ &lt;a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vim&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/prettier/vim-prettier"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/editorconfig/editorconfig-vim"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nvim&lt;/td&gt;
&lt;td&gt;✅ &lt;a href="https://prettier.io/docs/en/vim-plugin.html"&gt;Default&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;✅ &lt;a href="https://neovim.io/doc/user/editorconfig.html"&gt;Native&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IntelliJ IDEA&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://plugins.jetbrains.com/plugin/10456-prettier"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://www.jetbrains.com/help/idea/editorconfig.html"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sublime Text&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://packagecontrol.io/packages/JsPrettier"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://packagecontrol.io/packages/EditorConfig"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Atom&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/prettier/prettier-atom"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/sindresorhus/atom-editorconfig"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Emacs&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/prettier/prettier-emacs"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;✅ &lt;a href="https://github.com/editorconfig/editorconfig-emacs"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PyCharm&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://plugins.jetbrains.com/plugin/10456-prettier"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://www.jetbrains.com/help/idea/editorconfig.html"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eclipse&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/prettier/prettier-eclipse"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://marketplace.eclipse.org/content/editorconfig-eclipse"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Notepad++&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/prettier/prettier-notepad-plus-plus"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/editorconfig/editorconfig-notepad-plus-plus"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Brackets&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/prettier/prettier-brackets"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/kidwm/brackets-editorconfig"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebStorm&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://plugins.jetbrains.com/plugin/10456-prettier"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://www.jetbrains.com/help/idea/editorconfig.html"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PyCharm&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://plugins.jetbrains.com/plugin/10456-prettier"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://www.jetbrains.com/help/idea/editorconfig.html"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eclipse&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/prettier/prettier-eclipse"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://marketplace.eclipse.org/content/editorconfig-eclipse"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Notepad++&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/prettier/prettier-notepad-plus-plus"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;☑️ &lt;a href="https://github.com/editorconfig/editorconfig-notepad-plus-plus"&gt;Plugin&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And if you want to include these rules in linting locally or in the pipeline, even &lt;a href="https://prettier.io/docs/en/configuration.html#editorconfig"&gt;prettier supports it&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;I give you one better; usually I keep prettier settings like this &lt;code&gt;.prettierrc&lt;/code&gt; (or even better, stick it in &lt;code&gt;package.json&lt;/code&gt;'s prettier value):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"singleQuote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"printWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;140&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tabWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"useTabs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But you can go &lt;a href="https://www.boag.online/notepad/post/full-prettier-prettierrc-config"&gt;all-out&lt;/a&gt; if you want. The important thing is that there is a huge overlap with &lt;code&gt;.editorconfig&lt;/code&gt;:&lt;/p&gt;

&lt;h1&gt;
  
  
  Prettier and editorconfig feature comparison
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Prettier Setting&lt;/th&gt;
&lt;th&gt;.editorconfig Setting&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Indent Style&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useTabs: true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;indent_style = tab&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use tabs for indentation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useTabs: false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;indent_style = space&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use spaces for indentation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Indent Size&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tabWidth: N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;indent_size = N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Number of spaces or tabs for indentation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Line Length&lt;/td&gt;
&lt;td&gt;&lt;code&gt;printWidth: N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;max_line_length = N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maximum line length.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Newline Style&lt;/td&gt;
&lt;td&gt;&lt;code&gt;endOfLine: lf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;end_of_line = lf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use LF for line endings.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;endOfLine: crlf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;end_of_line = crlf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use CRLF for line endings.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;endOfLine: cr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;end_of_line = cr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use CR for line endings (rarely used).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trailing Spaces&lt;/td&gt;
&lt;td&gt;&lt;code&gt;trailingComma: none&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;trim_trailing_whitespace = true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Remove trailing whitespaces.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;trailingComma: es5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Add trailing commas where valid in ES5 syntax.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;trailingComma: all&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Add trailing commas in all places (arrays, objects, etc.).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tabs or Spaces&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;insert_final_newline = true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Insert a final newline at the end of files.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quote Style&lt;/td&gt;
&lt;td&gt;&lt;code&gt;singleQuote: true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Use single quotes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;singleQuote: false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Use double quotes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Experimental&lt;/td&gt;
&lt;td&gt;&lt;code&gt;singleAttributePerLine&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Experimental feature: format single attributes per line.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arrow Function&lt;/td&gt;
&lt;td&gt;&lt;code&gt;arrowParens: avoid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Avoid parentheses around a sole arrow function parameter.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;arrowParens: always&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Always include parentheses around arrow function parameters.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tab Width&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tabWidth: N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Number of spaces per tab.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Semicolons&lt;/td&gt;
&lt;td&gt;&lt;code&gt;semi: true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Use semicolons.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;semi: false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Omit semicolons.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSX Quotes&lt;/td&gt;
&lt;td&gt;&lt;code&gt;jsxSingleQuote: true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Use single quotes in JSX.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;jsxSingleQuote: false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Use double quotes in JSX.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bracket Spacing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bracketSpacing: true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Include spaces between brackets in object literals.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bracketSpacing: false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Exclude spaces between brackets in object literals.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prose Wrap&lt;/td&gt;
&lt;td&gt;&lt;code&gt;proseWrap: always&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Wrap prose text in Markdown or HTML as necessary.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;proseWrap: never&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Do not wrap prose text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;proseWrap: preserve&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Preserve existing line breaks.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tab Preferences&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tab_width = N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Number of spaces per tab when using spaces.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File Encoding&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;charset = utf-8&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;File character encoding.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Root Indicator&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;root = true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Marks the directory as the root for &lt;code&gt;.editorconfig&lt;/code&gt; settings.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Lab - funny discovery
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;I have a repo with no &lt;code&gt;.prettierrc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;I run &lt;code&gt;npx prettier . --write&lt;/code&gt;; I see some changes in the files; e.g. strings are now double quoted, breaks up lines &amp;gt; 80 chars etc. Very nice. &lt;/li&gt;
&lt;li&gt;I generate a clean default &lt;code&gt;.editorconfig&lt;/code&gt; using &lt;code&gt;npx editorconfig-cli init -y&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Without any configuration of prettier, when I run &lt;code&gt;npx prettier . --write&lt;/code&gt; again....
it respects the &lt;code&gt;quote_type&lt;/code&gt; = single and &lt;code&gt;max_line_length&lt;/code&gt; &lt;em&gt;from the .editorconfig&lt;/em&gt; ＼ ٩( ᐛ )و /／ ʕ•̫͡•ʕ&lt;em&gt;̫͡&lt;/em&gt;ʕ•͓͡•ʔ-̫͡-ʕ•̫͡•ʔ&lt;em&gt;̫͡&lt;/em&gt;ʔ-̫͡-ʔ &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My point is, why have a &lt;code&gt;.prettierrc&lt;/code&gt; file at all when all settings can be in &lt;code&gt;.editorconfig&lt;/code&gt; and still use prettier? At least you won't have conflicting settings. &lt;code&gt;.editorconfig&lt;/code&gt; file needs to be there anyway &lt;a href="https://github.com/editorconfig/editorconfig-core-js/issues/30"&gt;because you can't stick it in package.json&lt;/a&gt; like you can do with prettier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prettier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"semi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"singleQuote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"trailingComma"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"all"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is a huge win IMHO, however prettier is considered scoped within Node/Typescript/Javascript ecosystem, where editorconfig is more widely supported:&lt;/p&gt;

&lt;h1&gt;
  
  
  Language support prettier vs editorconfig
&lt;/h1&gt;

&lt;p&gt;Consider the current top 25 languages supported by Prettier and .editorconfig:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Prettier Support&lt;/th&gt;
&lt;th&gt;.editorconfig Support&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTML&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SCSS&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Markdown&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;YAML&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XML&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C++&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C#&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ruby&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PHP&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kotlin&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swift&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dart&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lua&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Groovy&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQL&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shell scripts&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Advice
&lt;/h1&gt;

&lt;p&gt;So my advice:&lt;/p&gt;

&lt;h2&gt;
  
  
  If you use multiple programming languages in one repo:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;use &lt;code&gt;.editorconfig&lt;/code&gt; everywhere&lt;/li&gt;
&lt;li&gt;let prettier use &lt;code&gt;.editorconfig&lt;/code&gt;, only use &lt;code&gt;.prettierrc&lt;/code&gt; to append settings &lt;code&gt;.editorconfig&lt;/code&gt; doesn't support, avoid conflicting settings. Use following script: &lt;code&gt;npx editorconfig-cli init -y&lt;/code&gt;, remove any prettier settings.&lt;/li&gt;
&lt;li&gt;include &lt;a href="https://prettier.io/docs/en/integrating-with-linters.html"&gt;prettier in eslint&lt;/a&gt; settings&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  If you only use TS/JS/HTML/CSS
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;totally ignore &lt;code&gt;.editorconfig&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;.prettierrc&lt;/code&gt; instead with prettier configuration&lt;/li&gt;
&lt;li&gt;include &lt;a href="https://prettier.io/docs/en/integrating-with-linters.html"&gt;prettier in eslint&lt;/a&gt; settings&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>editorconfig</category>
      <category>prettier</category>
      <category>format</category>
      <category>linting</category>
    </item>
    <item>
      <title>git command-line tricks</title>
      <dc:creator>Remi Kristelijn</dc:creator>
      <pubDate>Fri, 13 Dec 2019 09:26:47 +0000</pubDate>
      <link>https://forem.com/rkristelijn/git-command-line-tricks-24e8</link>
      <guid>https://forem.com/rkristelijn/git-command-line-tricks-24e8</guid>
      <description>&lt;p&gt;Personally I prefer command-line over tools. This has a few reasons;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The command-line is always available;&lt;/li&gt;
&lt;li&gt;If you can do it by commandline, you can do it everywhere&lt;/li&gt;
&lt;li&gt;Using the command-line makes me look geeky&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The reason for this post is that I grew tired of typing &lt;code&gt;git log --one-line -10&lt;/code&gt; that shows the last 10 commits and also having to type &lt;code&gt;q&lt;/code&gt; afterwards, where the information that I needed goes away, because I want to create a commit message that is in line with the rest of the commits. &lt;/p&gt;

&lt;p&gt;So I decided to look into making it more pleasant for me to quickly get some history information from git.&lt;/p&gt;

&lt;p&gt;The first thing I learned was that most git commands end up in a so called 'pager';&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git log --oneline -10&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;e3aa791 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt; notes
81affbd docs: translated installation guide and moved errors to bottom
9a592cd docs: nearly there
aaa98fe docs: add stuff from the thing
c522b66 docs: generic docs
e09ee2b chore&lt;span class="o"&gt;(&lt;/span&gt;Doc&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;sort
&lt;/span&gt;8740d11 chore&lt;span class="o"&gt;(&lt;/span&gt;doc&lt;span class="o"&gt;)&lt;/span&gt;: add new stuff
bd8e74c notes after meeting
0de07df chore&lt;span class="o"&gt;(&lt;/span&gt;Base&lt;span class="o"&gt;)&lt;/span&gt;: initial checkin
&lt;span class="o"&gt;(&lt;/span&gt;END&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I discovered that I can bypass the pager so that git uses &lt;code&gt;cat&lt;/code&gt; by adding &lt;code&gt;--no-pager&lt;/code&gt; as first argument. It only works as a first argument.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;--no-pager&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;git --no-pager log --oneline -10&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;➜  notes git:&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt; git &lt;span class="nt"&gt;--no-pager&lt;/span&gt; log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;-10&lt;/span&gt;
e3aa791 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt; notes
81affbd docs: translated installation guide and moved errors to bottom
9a592cd docs: nearly there
aaa98fe docs: add kostenscherm
c522b66 docs: generic docs
e09ee2b chore&lt;span class="o"&gt;(&lt;/span&gt;Doc&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;sort
&lt;/span&gt;8740d11 chore&lt;span class="o"&gt;(&lt;/span&gt;doc&lt;span class="o"&gt;)&lt;/span&gt;: add new stuff
bd8e74c notes after meeting
0de07df chore&lt;span class="o"&gt;(&lt;/span&gt;Base&lt;span class="o"&gt;)&lt;/span&gt;: initial checkin
➜  notes git:&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;notice how I get my shell back and the information is still on my screen. Now I could write a git commit message in line with the rest.&lt;/p&gt;

&lt;p&gt;So this solves part of my problem. I don't want to type the whole command as above over and over again. It is nice to remember it when you are working on someone else's machine, but in this case I want to 'save' it.&lt;/p&gt;

&lt;p&gt;The good news is; you can. per command, you can toggle whether it should use pager.&lt;/p&gt;

&lt;p&gt;In this case you can type:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git config --global pager.log false&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;➜  notes git:&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt; git config &lt;span class="nt"&gt;--global&lt;/span&gt; pager.log &lt;span class="nb"&gt;false&lt;/span&gt;
➜  notes git:&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt; git log &lt;span class="nt"&gt;-1&lt;/span&gt;
commit e3aa791e0e970023734988c8aeb736ecda6099f4 &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master&lt;span class="o"&gt;)&lt;/span&gt;
Author: Remi Kristelijn &amp;lt;remi.kristelijn@myawesomecompany.com&amp;gt;
Date:   Fri Nov 29 15:51:02 2019 +0100

    notes
➜  notes git:&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;These settings are stored in &lt;code&gt;~/.gitconfig&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Also I know with combination of &lt;code&gt;--pretty&lt;/code&gt; and &lt;code&gt;--graph&lt;/code&gt; you can decorate you log message and save this as an alias.&lt;/p&gt;

&lt;h1&gt;
  
  
  Adding an alias
&lt;/h1&gt;

&lt;p&gt;The command I use is &lt;code&gt;log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset' -10&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;➜  git:&lt;span class="o"&gt;(&lt;/span&gt;master&lt;span class="o"&gt;)&lt;/span&gt; git log &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s1"&gt;'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset'&lt;/span&gt; &lt;span class="nt"&gt;-10&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt;   d2a1b98 - &lt;span class="o"&gt;(&lt;/span&gt;HEAD -&amp;gt; master, origin/master&lt;span class="o"&gt;)&lt;/span&gt; Merge branch &lt;span class="s1"&gt;'feat/wizard-steps'&lt;/span&gt; into &lt;span class="s1"&gt;'master'&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;Remi Kristelijn&amp;gt;
|&lt;span class="se"&gt;\ &lt;/span&gt; 
| &lt;span class="k"&gt;*&lt;/span&gt; 20b7b2e - &lt;span class="o"&gt;(&lt;/span&gt;origin/feat/wizard-steps, feat/wizard-steps&lt;span class="o"&gt;)&lt;/span&gt; feat:step 2 of wizard &lt;span class="o"&gt;(&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;Remi Kristelijn&amp;gt;
| &lt;span class="k"&gt;*&lt;/span&gt; 077f5e1 - feat: wizard placeholder &lt;span class="o"&gt;(&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;Remi Kristelijn&amp;gt;
| &lt;span class="k"&gt;*&lt;/span&gt; e2f4c29 - feat: add readme.md as an example &lt;span class="o"&gt;(&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;Remi Kristelijn&amp;gt;
| &lt;span class="k"&gt;*&lt;/span&gt; debbfcd - fix: hyperlink goes outside of context &lt;span class="o"&gt;(&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;Remi Kristelijn&amp;gt;
| &lt;span class="k"&gt;*&lt;/span&gt; af11d21 - feat:allow &lt;span class="k"&gt;*&lt;/span&gt;.md imports &lt;span class="k"&gt;for &lt;/span&gt;Typescript &lt;span class="o"&gt;(&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;Remi Kristelijn&amp;gt;
|/  
&lt;span class="k"&gt;*&lt;/span&gt;   cb562e3 - Merge branch &lt;span class="s1"&gt;'feat/style'&lt;/span&gt; into &lt;span class="s1"&gt;'master'&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;Remi Kristelijn&amp;gt;
|&lt;span class="se"&gt;\ &lt;/span&gt; 
| &lt;span class="k"&gt;*&lt;/span&gt;   51df26c - &lt;span class="o"&gt;(&lt;/span&gt;origin/feat/style, feat/style&lt;span class="o"&gt;)&lt;/span&gt; fix:merge &lt;span class="o"&gt;(&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;Remi Kristelijn&amp;gt;
| |&lt;span class="se"&gt;\ &lt;/span&gt; 
| |/  
|/|   
&lt;span class="k"&gt;*&lt;/span&gt; |   3583c92 - Merge branch &lt;span class="s1"&gt;'feat/docs'&lt;/span&gt; into &lt;span class="s1"&gt;'master'&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;Remi Kristelijn&amp;gt;
|&lt;span class="se"&gt;\ \ &lt;/span&gt; 
| &lt;span class="k"&gt;*&lt;/span&gt; | ba0f827 - &lt;span class="o"&gt;(&lt;/span&gt;origin/feat/docs&lt;span class="o"&gt;)&lt;/span&gt; docs:add loglevel &lt;span class="o"&gt;(&lt;/span&gt;3 weeks ago&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;Remi Kristelijn&amp;gt;%  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To save this command as an alias, let's say &lt;code&gt;lg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git config --global alias.lg log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset' -10&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then you can flag this command to also not use 'pager'&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git config --global pager.lg false&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But because log is already flagged false for pager, it will cary that through when using lg.&lt;/p&gt;

</description>
      <category>git</category>
      <category>commandline</category>
    </item>
    <item>
      <title>Simplest login app using express-session</title>
      <dc:creator>Remi Kristelijn</dc:creator>
      <pubDate>Fri, 05 Jul 2019 17:46:54 +0000</pubDate>
      <link>https://forem.com/rkristelijn/simplest-login-app-using-express-session-gio</link>
      <guid>https://forem.com/rkristelijn/simplest-login-app-using-express-session-gio</guid>
      <description>&lt;h1&gt;
  
  
  Express login with express-session
&lt;/h1&gt;

&lt;p&gt;Clone &lt;a href="https://github.com/rkristelijn/login/" rel="noopener noreferrer"&gt;this repo&lt;/a&gt; or follow the steps below to learn about setting up a Node/express app that enables login, logout and secure routes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;step&lt;/th&gt;
&lt;th&gt;instruction&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;0. boilerplating&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;These steps will set up an initial project.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.1&lt;/td&gt;
&lt;td&gt;Install &lt;a href="https://www.npmjs.com/package/express-generator" rel="noopener noreferrer"&gt;express-generator&lt;/a&gt; globally &lt;code&gt;npm install -g express-generator&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.2&lt;/td&gt;
&lt;td&gt;Create a new project named &lt;strong&gt;login&lt;/strong&gt; in a new folder &lt;strong&gt;login&lt;/strong&gt; and add pug support (instead of Jade). &lt;code&gt;express -css=less --view=pug --git login&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.3&lt;/td&gt;
&lt;td&gt;Install dependencies by executing &lt;code&gt;npm i&lt;/code&gt; after moving into the directory using &lt;code&gt;cd login&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.4&lt;/td&gt;
&lt;td&gt;You will see warnings, depending on how many vulnerabilities are found.&lt;br&gt; &lt;code&gt;npm notice created a lockfile as package-lock.json. You should commit this file.&lt;/code&gt;&lt;br&gt;&lt;code&gt;added 118 packages from 174 contributors and audited 247 packages in 10.793s&lt;/code&gt;&lt;br&gt;&lt;code&gt;found 1 low severity vulnerability run npm audit fix to fix them, or npm audit for details&lt;/code&gt;&lt;br&gt; after running &lt;code&gt;npm audit&lt;/code&gt; you will see recommendations to fix, you might want to run &lt;code&gt;npm ls&lt;/code&gt; to see the dependency tree.&lt;br&gt;In this case you can fix it by running &lt;code&gt;npm i pug@latest&lt;/code&gt;&lt;br&gt;&lt;br&gt;After running this no vulnerabilities are reported and we can go ahead and start the app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.5&lt;/td&gt;
&lt;td&gt;start the app by one of the following commands: &lt;br&gt; 1. &lt;code&gt;npm start&lt;/code&gt; - &lt;em&gt;to start app on default port 3000&lt;/em&gt;&lt;br&gt;2. &lt;code&gt;PORT=8080 npm start&lt;/code&gt; - &lt;em&gt;to start on port 8080&lt;/em&gt;&lt;br&gt;3. &lt;code&gt;DEBUG=login:* npm start&lt;/code&gt; - &lt;em&gt;start with debug information&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.6&lt;/td&gt;
&lt;td&gt;Point your browser to &lt;code&gt;localhost:3000&lt;/code&gt; &lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi9wn4mgqtb4thfg9u3tw.png" width="508" height="350"&gt; &lt;br&gt; In our console we see:&lt;br&gt;&lt;code&gt;~/login$ DEBUG=login:* npm start&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;code&gt;&amp;gt; login@0.0.0 start /home/gius/login&lt;/code&gt;&lt;br&gt;&lt;code&gt;&amp;gt; node ./bin/www&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;code&gt;login:server Listening on port 3000 +0ms&lt;/code&gt;&lt;br&gt;&lt;code&gt;GET / 304 719.979 ms - -&lt;/code&gt;&lt;br&gt;&lt;code&gt;GET /stylesheets/style.css 304 7.148 ms - -&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;1. create login form&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;After completing these steps we have a new page and route.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.1&lt;/td&gt;
&lt;td&gt;run &lt;code&gt;npm i --save express-session bootstrap&lt;/code&gt; to add the dependency&lt;br&gt;Note that bootstrap has 2 peer dependencies: jquery and popper.js. We don't need these, because we are just going to use the css. This is a list of ways to handle the &lt;code&gt;npm WARN&lt;/code&gt;:&lt;br&gt;1. Ignore the warnings; &lt;em&gt;not desired because the team will ignore all npm output&lt;/em&gt;&lt;br&gt;2. Install peer deps: &lt;code&gt;npm i --save jquery popper.js&lt;/code&gt;; &lt;em&gt;not desired; packers will include jquery and popper.js and let the codebase grow significantly&lt;/em&gt;&lt;br&gt;3. Install as dev deps: &lt;code&gt;npm i -D jquery popper.js&lt;/code&gt;; &lt;em&gt;Unsure yet if it solves 2, but it shuts up the WARN&lt;/em&gt;&lt;br&gt;4. Use &lt;a href="https://github.com/codejamninja/ignore-warnings" rel="noopener noreferrer"&gt;ignore-warings&lt;/a&gt;: &lt;em&gt;Unclear &lt;a href="https://github.com/codejamninja/ignore-warnings/issues/2" rel="noopener noreferrer"&gt;how to use&lt;/a&gt; yet, but it seems like a legit way of avoiding 2 and still keep npm output clean&lt;/em&gt;&lt;br&gt;5. use bootstrap cdn; &lt;em&gt;Preferred to install locally to allow offline dev&lt;/em&gt;&lt;br&gt;6. manual install bootstrap; &lt;em&gt;deps should be in package.json for keeping all updatable and visable for npm audit&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.2&lt;/td&gt;
&lt;td&gt;create &lt;code&gt;/views/login.pug&lt;/code&gt; &lt;a href="https://github.com/rkristelijn/login/commit/e3c94bb22d43140f0a18054c793572fca60ce7ae#diff-6d5d452b8670045112ed889367008056" rel="noopener noreferrer"&gt;see change&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.3&lt;/td&gt;
&lt;td&gt;add the route to &lt;code&gt;app.js&lt;/code&gt; for reroute to login, bootstrap and include session &lt;a href="https://github.com/rkristelijn/login/commit/e3c94bb22d43140f0a18054c793572fca60ce7ae#diff-0364f57fbff2fabbe941ed20c328ef1a" rel="noopener noreferrer"&gt;see change&lt;/a&gt;&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;update styles &lt;code&gt;public/style.css&lt;/code&gt; &lt;a href="https://github.com/rkristelijn/login/commit/e3c94bb22d43140f0a18054c793572fca60ce7ae#diff-0aaa9d35a8082eda23139c53348d2e51" rel="noopener noreferrer"&gt;see change&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.5&lt;/td&gt;
&lt;td&gt;update layout.pug to include bootstrap &lt;code&gt;views/layout.pug&lt;/code&gt; &lt;a href="https://github.com/rkristelijn/login/commit/e3c94bb22d43140f0a18054c793572fca60ce7ae#diff-5c5792469bc79f8d2ab44b4192b02a20" rel="noopener noreferrer"&gt;see change&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.6&lt;/td&gt;
&lt;td&gt;current result routes default route to login&lt;br&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpo5ccvcr0imvhi9b30b.png" width="800" height="447"&gt;&lt;br&gt;&lt;code&gt;~/login $ DEBUG=login:* npm start -s&lt;/code&gt;&lt;br&gt;&lt;code&gt;login:server Listening on port 3000 +0ms&lt;/code&gt;&lt;br&gt;&lt;code&gt;GET / 304 737.652 ms - -&lt;/code&gt;&lt;br&gt;&lt;code&gt;GET /css/bootstrap.min.css 304&lt;/code&gt;&lt;br&gt;&lt;code&gt;.766 ms - -&lt;/code&gt;&lt;br&gt;&lt;code&gt;GET /stylesheets/style.css 304 1.070 ms - -&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;2. add about-page and header&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Follow below steps to add about page and header&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.1&lt;/td&gt;
&lt;td&gt;Before we continue, I like to clean up some logging. &lt;code&gt;morgan&lt;/code&gt; is creating too much noise. Remove the following lines from &lt;code&gt;app.js&lt;/code&gt;:&lt;br&gt;&lt;code&gt;var logger = require("morgan");&lt;/code&gt;&lt;br&gt;&lt;code&gt;app.use(logger("dev"));&lt;/code&gt;&lt;br&gt;&lt;br&gt;You can remove morgan from &lt;code&gt;package.json&lt;/code&gt; by: &lt;br&gt;&lt;code&gt;npm rm --save morgan&lt;/code&gt;.&lt;br&gt;&lt;br&gt;While we are at it; &lt;code&gt;debug&lt;/code&gt; is a direct dependency for &lt;code&gt;express&lt;/code&gt; and &lt;code&gt;express-session&lt;/code&gt; so we can remove it from our &lt;code&gt;package.json&lt;/code&gt; by: &lt;br&gt;&lt;code&gt;npm rm --save debug&lt;/code&gt;.&lt;br&gt;&lt;br&gt;To see if &lt;code&gt;debug&lt;/code&gt; still works, we can use:&lt;br&gt;&lt;code&gt;DEBUG=app.js,login:server,express-session npm start -s&lt;/code&gt;. Note that we can use &lt;code&gt;DEBUG=*&lt;/code&gt; for all output.&lt;br&gt;&lt;br&gt;Now we can add debug info like so (in app.js): &lt;br&gt;&lt;code&gt;var debug = require('debug')('app.js');&lt;/code&gt; &lt;br&gt; &lt;code&gt;debug('hello world');&lt;/code&gt;&lt;br&gt;&lt;br&gt;Our output:&lt;br&gt;&lt;code&gt;login:server Listening on port 3001 +0ms&lt;/code&gt;&lt;br&gt;&lt;code&gt;express-session no SID sent, generating session +26s&lt;/code&gt;&lt;br&gt;&lt;code&gt;app.js checkLoggedIn(), req.session.loggedIn: undefined rendering login +5ms&lt;/code&gt;&lt;br&gt;&lt;code&gt;express-session saving PybLKV4TpsaSMx_PzZx_Mj5Is4X_0U9g +748ms&lt;/code&gt;&lt;br&gt;&lt;code&gt;express-session set-cookie app=s%3APybLKV4TpsaSMx_PzZx_Mj5Is4X_0U9g.Bd1dSB8w4kfcL9DPonfLBXFRLtZBdqHThCNMTsv0Ixo; Path=/; HttpOnly +4ms&lt;/code&gt;&lt;br&gt;&lt;code&gt;express-session fetching PybLKV4TpsaSMx_PzZx_Mj5Is4X_0U9g +736ms&lt;/code&gt;&lt;br&gt;&lt;code&gt;express-session session found +1ms&lt;/code&gt;&lt;br&gt;&lt;code&gt;app.js checkLoggedIn(), req.session.loggedIn: undefined rendering login +1ms&lt;/code&gt;&lt;br&gt;&lt;code&gt;express-session saving PybLKV4TpsaSMx_PzZx_Mj5Is4X_0U9g +93ms&lt;/code&gt;&lt;br&gt;&lt;code&gt;express-session split response +1ms&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.2&lt;/td&gt;
&lt;td&gt;add &lt;code&gt;routes/about.js&lt;/code&gt; and &lt;code&gt;views/about.pug&lt;/code&gt; with &lt;a href="https://github.com/rkristelijn/login/commit/e8c1317536cad9cde82169d40f05ffd68534e112#diff-8bd0aaff64e2da1404cfd91cce49a9f8" rel="noopener noreferrer"&gt;this content&lt;/a&gt; and update &lt;code&gt;app.js&lt;/code&gt;; add: &lt;br&gt;&lt;code&gt;app.use("/about", aboutRouter);&lt;/code&gt;&lt;br&gt;&lt;code&gt;var aboutRouter = require("./routes/about");&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.3&lt;/td&gt;
&lt;td&gt;add &lt;code&gt;views/header.pug&lt;/code&gt; with &lt;a href="https://github.com/rkristelijn/login/commit/e8c1317536cad9cde82169d40f05ffd68534e112#diff-2e915f5980f834b4e8d3c8c06bcc292a" rel="noopener noreferrer"&gt;this content&lt;/a&gt; and include it in &lt;code&gt;index.pug&lt;/code&gt; and &lt;code&gt;users.pug&lt;/code&gt; and conditionally in &lt;code&gt;views/about.pug&lt;/code&gt;:&lt;br&gt;&lt;code&gt;if loggedIn&lt;/code&gt;&lt;br&gt;    &lt;code&gt;include header&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.4&lt;/td&gt;
&lt;td&gt;then there are some bits and pieces to fix in &lt;code&gt;views/login.pug&lt;/code&gt;:&lt;br&gt;- add error placeholder&lt;br&gt;- add link to about page&lt;br&gt;- change button to input, so the enter key works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2.5&lt;/td&gt;
&lt;td&gt;add &lt;code&gt;views/users.pug&lt;/code&gt; with contents from &lt;a href="https://github.com/rkristelijn/login/commit/e8c1317536cad9cde82169d40f05ffd68534e112#diff-e804aa6e48ffa93374f7428688bf657b" rel="noopener noreferrer"&gt;here&lt;/a&gt; and pass a list of users &lt;a href="https://github.com/rkristelijn/login/commit/e8c1317536cad9cde82169d40f05ffd68534e112#diff-e9f8fcf8d0b7b7150ff1c16a7c69ea74" rel="noopener noreferrer"&gt;like so&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;3. finalize login&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;There still stuff left to do. The examples just support login and logout, and the session is killed after 6000 ms (6sec)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3.1&lt;/td&gt;
&lt;td&gt;We can remove the line &lt;code&gt;cookie: {maxAge: 6000}&lt;/code&gt; so the session isn't just 6sec from &lt;code&gt;app.js&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3.2&lt;/td&gt;
&lt;td&gt;In &lt;code&gt;app.js&lt;/code&gt; we create a &lt;code&gt;login()&lt;/code&gt;- and a &lt;code&gt;logout()&lt;/code&gt; function that only care about logging in and logging out.&lt;br&gt;&lt;br&gt;Logout removes the session.loggedIn flag, Login sets it and calls checking the credentials. A separate function is created to check the credentials called &lt;code&gt;checkUser()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Final design
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nSQYC4g2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/rkristelijn/login/blob/master/doc/diagrams/views.activity.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nSQYC4g2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/rkristelijn/login/blob/master/doc/diagrams/views.activity.svg%3Fraw%3Dtrue" width="800" height="674"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Final Demo
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;clean start &lt;code&gt;/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;get &lt;code&gt;/about&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;get &lt;code&gt;/users&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;login&lt;/li&gt;
&lt;li&gt;homepage&lt;/li&gt;
&lt;li&gt;get &lt;code&gt;/users&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;get &lt;code&gt;/about&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;logout&lt;/li&gt;
&lt;li&gt;wrong login&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0cv6694r9kayb2co5vfq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0cv6694r9kayb2co5vfq.gif" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Questions / evaluation
&lt;/h1&gt;

&lt;p&gt;These are answers that I seek answer to before starting this document, raised during creation and reviewing the code.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Do I need passport and passport local for logging in?&lt;/td&gt;
&lt;td&gt;no. Minimum is &lt;code&gt;express&lt;/code&gt;, &lt;code&gt;express-session&lt;/code&gt; and maybe &lt;code&gt;cookie-parse&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is the simplest way of creating login/logout? Cookies? Server-side session?&lt;/td&gt;
&lt;td&gt;This solution creates a cookie even when the user isn't logged in. This is a &lt;a href="https://decodeproject.eu/cookies" rel="noopener noreferrer"&gt;session cookie&lt;/a&gt;.&lt;br&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--etwBbRIa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/v1/./doc/images/cookie.png" width="" height=""&gt;&lt;br&gt;&lt;br&gt;The value is&lt;br&gt;&lt;code&gt;s%3Ayz92aWlUKzWDXhzlkqiz8wddo-SH2G0I.N6dzg2O0liagsejyMKLehW1aRGL6fEY1mkMrTFKOG1E&lt;/code&gt; that seems to be the same value as the session on the server in the console of &lt;code&gt;DEBUG=express-session npm start -s&lt;/code&gt;. &lt;br&gt;More on &lt;a href="https://flaviocopes.com/cookies/" rel="noopener noreferrer"&gt;cookie security&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can I identify the user, so I can create access groups and allow different routes per user?&lt;/td&gt;
&lt;td&gt;No. In this case only a boolean is stored:&lt;br&gt;&lt;code&gt;Session {&lt;/code&gt;&lt;br&gt;    &lt;code&gt;cookie: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true },&lt;/code&gt;&lt;br&gt;    &lt;code&gt;loggedIn: true&lt;/code&gt;&lt;br&gt;&lt;code&gt;}&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Is this the simplest example?&lt;/td&gt;
&lt;td&gt;For testing the session, you need at least 1 or 2 'secure' routes, login- and logout route and some kind of views. With a SPA the backend can be smaller.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;is creating &lt;code&gt;req.session.loggedIn&lt;/code&gt; a legit way to manage the session?&lt;/td&gt;
&lt;td&gt;For now it seems ok.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What are generic security recommendations?&lt;/td&gt;
&lt;td&gt;On the &lt;a href="https://github.com/expressjs/session#sessionoptions" rel="noopener noreferrer"&gt;express-session&lt;/a&gt; page it says: &lt;br&gt;&lt;strong&gt;Warning&lt;/strong&gt; The default server-side session storage, MemoryStore, is purposely not designed for a production environment. It will leak memory under most conditions, does not scale past a single process, and is meant for debugging and developing. It seems &lt;a href="https://www.npmjs.com/package/connect-mongodb-session" rel="noopener noreferrer"&gt;MongoDB can store the session&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Sources
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://projectsplaza.com/login-logout-nodejs-express/" rel="noopener noreferrer"&gt;original tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@nima.2004hkh/create-your-first-login-page-with-exprerssjs-pug-f42250229486" rel="noopener noreferrer"&gt;another tutor from Nima HKH&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.jyotman.xyz/post/logging-in-node.js-done-right" rel="noopener noreferrer"&gt;node logging done right&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>express</category>
      <category>session</category>
      <category>node</category>
      <category>login</category>
    </item>
    <item>
      <title>my jsend implementation in node</title>
      <dc:creator>Remi Kristelijn</dc:creator>
      <pubDate>Fri, 05 Jul 2019 17:35:19 +0000</pubDate>
      <link>https://forem.com/rkristelijn/my-jsend-implementation-in-node-28b2</link>
      <guid>https://forem.com/rkristelijn/my-jsend-implementation-in-node-28b2</guid>
      <description>&lt;h1&gt;
  
  
  JSend
&lt;/h1&gt;

&lt;p&gt;This is my implementation of jsend. You can fork/clone the repo and give me your feedback. I tried to stick with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All responses return json (including errors)&lt;/li&gt;
&lt;li&gt;Limit HTTP.status to

&lt;ul&gt;
&lt;li&gt;200 OK&lt;/li&gt;
&lt;li&gt;400 BAD REQUEST (client fault)&lt;/li&gt;
&lt;li&gt;500 INTERNAL SERVER ERROR (server fault)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;On top of 1 and 2, use &lt;a href="https://github.com/omniti-labs/jsend"&gt;jsend&lt;/a&gt; standard, but all 4 fields are always returned:

&lt;ul&gt;
&lt;li&gt;status - [OK,FAIL,ERROR],&lt;/li&gt;
&lt;li&gt;data - the data or the stack&lt;/li&gt;
&lt;li&gt;message - shortest message possible&lt;/li&gt;
&lt;li&gt;code - [200,400,500]&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The drivers for these 3 points is, that this REST API should serve a frontend with limited exotic situations where the server all of a sudden responds with HTML or different structure.&lt;/p&gt;

&lt;p&gt;The code can be found here: &lt;a href="https://github.com/rkristelijn/jsend"&gt;https://github.com/rkristelijn/jsend&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I did not implement POST, PUT and DELETE (yet), so it is not a full REST service.&lt;/p&gt;

&lt;h1&gt;
  
  
  Install
&lt;/h1&gt;

&lt;p&gt;With SSH:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:rkristelijn/jsend.git
&lt;span class="nb"&gt;cd &lt;/span&gt;jsend &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm i
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With HTTP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/rkristelijn/jsend.git
&lt;span class="nb"&gt;cd &lt;/span&gt;jsend &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm i
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Usage
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;purpose&lt;/th&gt;
&lt;th&gt;command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;start&lt;/td&gt;
&lt;td&gt;&lt;code&gt;npm start -s&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;test&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;npm test -s&lt;/code&gt; (after server is running)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Demo
&lt;/h1&gt;

&lt;p&gt;&lt;a href="//github.com/rkristelijn/jsend/blob/master/doc/demo.gif?raw=true" class="article-body-image-wrapper"&gt;&lt;img src="//github.com/rkristelijn/jsend/blob/master/doc/demo.gif?raw=true" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Responses
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;GET /&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SUCCESS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000/api"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"200: OK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;GET /api&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FAIL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Route '/api' not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"400: BAD REQUEST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Route '/api' not found"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"available"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000/api/users"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000/api/fail"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;GET /api/users&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SUCCESS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"system"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"henk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"annie"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"200: OK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;GET /api/users/henk&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SUCCESS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"henk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"pass"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"annie"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"200: OK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;GET /api/fail&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I purposely created an error, calling &lt;code&gt;i_will_crash_on_purpose()&lt;/code&gt; that doesn't exist to see if a proper JSON is returned.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ERROR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"i_will_crash_on_purpose is not defined"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"500: INTERNAL SERVER ERROR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"ReferenceError: i_will_crash_on_purpose is not defined"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"at /home/gius/jsend/api/fail/fail-router.js:10:5"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Key take-aways
&lt;/h1&gt;

&lt;h2&gt;
  
  
  npm WARN
&lt;/h2&gt;

&lt;p&gt;Ignore the WARN per heavily discussed fsevent optional dependency for chokidar (via nodemon) in npm &lt;a href="https://github.com/yarnpkg/yarn/issues/3738"&gt;here&lt;/a&gt; on non-mac systems. There seems no way around it, like I did with the jQuery dependency &lt;a href="https://github.com/rkristelijn/login"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  console.log() vs debug()
&lt;/h2&gt;

&lt;p&gt;Debug comes as a dependency of express. Debug can be tailored at the beginning of every file and filtered while starting the app.&lt;/p&gt;

&lt;p&gt;you can use a .env file and &lt;a href="https://www.npmjs.com/package/dotenv"&gt;dotenv&lt;/a&gt; or simply add the following to the start script in package.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PORT=3000 DEBUG=jsend* nodemon ./bin/www"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Custom validators in test
&lt;/h2&gt;

&lt;p&gt;To keep the test clean, I've written 3 simple validators for jsend that can be reused and keep the test themselves short, manageable and reusable.&lt;/p&gt;

&lt;h2&gt;
  
  
  e2e test without bootstrapping the app
&lt;/h2&gt;

&lt;p&gt;The test might as well skip setting up the app in before(). This removes redundant code, makes the test simpler and test the actual app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arrow-functions / lambdas in test
&lt;/h2&gt;

&lt;p&gt;This is not best practice because of this scope is gone. Mocha strongly &lt;a href="https://mochajs.org/#arrow-functions"&gt;advices to avoid lambda's in test&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Passing arrow functions (aka "lambdas") to Mocha is discouraged. Lambdas lexically bind this and cannot access the Mocha context.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Sources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/12806386/standard-json-api-response-format"&gt;question about JSON Standards&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jsonapi.org/implementations/#server-libraries-node-js"&gt;already existing implementation of jsend&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://expressjs.com/en/guide/error-handling.html"&gt;error handling in node&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>jsend</category>
      <category>express</category>
      <category>node</category>
      <category>rest</category>
    </item>
    <item>
      <title>JavaScript developer's visualization and design</title>
      <dc:creator>Remi Kristelijn</dc:creator>
      <pubDate>Wed, 19 Jun 2019 12:56:20 +0000</pubDate>
      <link>https://forem.com/rkristelijn/javascript-developer-s-visualization-and-design-39hp</link>
      <guid>https://forem.com/rkristelijn/javascript-developer-s-visualization-and-design-39hp</guid>
      <description>&lt;p&gt;A few weeks ago I made a small contribution to a github repo. This is actually something I do often when I want to try out stuff from another developer; I clone the repo, usually there's some outdated dependencies or error in the installation instruction, how hard is it to fork it and make a PR? Usually this is highly appreciated.&lt;/p&gt;

&lt;p&gt;In this case it was a project that I use very often, which is a plugin in Visual Studio Code called &lt;a href="https://marketplace.visualstudio.com/items?itemName=JaimeOlivares.yuml"&gt;yUML&lt;/a&gt;. I use this to visualize my code, or idea before I key it in. It is very simple; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;you create a new *.yuml file, and type one of the following words: [class|activity|usecase|state|deployment|package|sequence] and an example is pre-generated for you, visualizing the diagram desired so you can start tinkering around to your desire. When done, you add &lt;code&gt;// {generate:true}&lt;/code&gt; to the top and you can import your design in your .md file using `&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lVCT5eyD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/v1/./path/to/class.diagram.svg" alt=""&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I found that the examples were a bit hard to find. So I contributed to the wiki, so whenever you press 'wiki' in the preview, you see my contribution.&lt;/p&gt;

&lt;p&gt;Next to that I found two other projects that are similar:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=FlomoN.chartjs-markdown-preview"&gt;Chart.js Markdown Preview&lt;/a&gt; however this doesn't work on github&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=tomoyukim.vscode-mermaid-editor"&gt;Mermaid Editor&lt;/a&gt; that you can manually generate svg files from, which is not as strict as &lt;a href="https://marketplace.visualstudio.com/items?itemName=JaimeOlivares.yuml"&gt;yUML&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'd love to hear about your (free) visualization techniques that work cross-os without having to install complex programs!&lt;/p&gt;

</description>
      <category>uml</category>
      <category>visualstudiocode</category>
      <category>design</category>
    </item>
  </channel>
</rss>
