<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://staxmanade.com</id>
    <title><![CDATA[Developing on Staxmanade]]></title>
    <updated>2019-05-12T17:54:12.628Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <author>
        <name>Jason Jarrett</name>
        <uri>https://staxmanade.com/about</uri>
    </author>
    <link rel="alternate" href="https://staxmanade.com"/>
    <link rel="self" href="http://feeds.feedburner.com/DevelopingOnStaxmande"/>
    <rights>Copyright (C) 2008-2023 Jason Jarrett</rights>
    <entry>
        <title type="html"><![CDATA[Spend the Effort to Make Your Tests Better Documentation]]></title>
        <id>https://staxmanade.com/2019/05/spend-the-effort-to-make-your-tests-better-documentation/</id>
        <link href="https://staxmanade.com/2019/05/spend-the-effort-to-make-your-tests-better-documentation/">
        </link>
        <updated>2019-05-12T17:54:12.628Z</updated>
        <summary type="html"><![CDATA[You may be writing tests, but are they describing the behavior well enough to know what business case it's covering a year from now?]]></summary>
        <content type="html"><![CDATA[<p>You may be writing tests, but are they describing the behavior well enough to know what business case it's covering a year from now?</p>
<p>Today's lesson or re-lesson. <a href="https://staxmanade.com/2012/01/you-are-responsible-for-making-that/">Don't just write your tests</a>, <em>write it so you can understand the intricacies a year from now</em>.</p>
<p>The other day I was pairing on a what we first thought was a bug in our software. I was explaining something we saw.. &quot;oh yea, that's a bug, oh and look at these tests, they look wrong also. Why is this so wrong? How did we not catch this last year? Something is off here... etc...&quot;</p>
<p>While I had some tests to cover a business requirement a year ago when we wrote the software, I had not properly described the business case within the test to document it's purpose.</p>
<p>The subtle, bug-look-a-likes turned out to be proper behavior. If only I had not just documented the expected behavior via a test, but had properly describe WHY this behavior existed within the test, we could have avoided potentially breaking it (by &quot;trying to fix it&quot;) and the test could have better communicated the WHY of this strange case.</p>
<p>This is just a reminder to myself to write better tests. Doing tests, great. Well documented, business explanation of the WHY in the tests? Way better!</p>
<p>Happy testing!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[JavaScript - Refactoring too many function params]]></title>
        <id>https://staxmanade.com/2019/05/javascript---refactoring-too-many-function-params/</id>
        <link href="https://staxmanade.com/2019/05/javascript---refactoring-too-many-function-params/">
        </link>
        <updated>2019-05-12T00:24:41.588Z</updated>
        <summary type="html"><![CDATA[A code smell that can creep into your JavaScript codebase and quickly make the code difficult to follow is when a function has too many parameters.]]></summary>
        <content type="html"><![CDATA[<p>A code smell that can creep into your JavaScript codebase and quickly make the code difficult to follow is when a function has too many parameters.</p>
<p>EX:</p>
<pre><code>myFunction(<span class="hljs-string">"val1"</span>, <span class="hljs-number">1</span>, <span class="hljs-literal">true</span>, <span class="hljs-literal">false</span>, <span class="hljs-literal">false</span>, <span class="hljs-literal">true</span>);
</code></pre>
<p>Looking at the above, we can sort of tell that the first param is some string, maybe we can even tell what it's purpose is, the second a number maybe we even know why if we understand the codebase. But the booleans that follow? What are those representing? How do you know you're providing the right value for the right argument?</p>
<p>One approach is to refactor those parameters into variable names to help give them meaning.</p>
<p>EX:</p>
<pre><code><span class="hljs-variable"><span class="hljs-keyword">var</span> firstName</span> = <span class="hljs-string">"val1"</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> age</span> = <span class="hljs-number">1</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> isCool</span> = <span class="hljs-literal">true</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> isHungry</span> = <span class="hljs-literal">false</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> isSleeping</span> = <span class="hljs-literal">false</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> isHappy</span> = <span class="hljs-literal">true</span>;
myFunction(firstName, age, isCool, isHungry, isSleeping, isHappy);
</code></pre>
<p>Now at least when we look at each parameter we can see it's name and that helps give some context of what it represents.</p>
<p>But as this parameter list grows it can be difficult to maintain. We could argue it's already too long.</p>
<p>What if you have to add a parameter in the middle?</p>
<p>How can you be sure all the callers get updated correctly?</p>
<p>Another approach would be to refactor this list of parameters into an object of properties.</p>
<p>This comes with some benefits like, you can add/remove properties without worrying about parameter ordering, as long as they can be optional and have solid defaults.</p>
<p>One cool thing I found with ES6 destructuring and enhanced object literals is if our function definition AND our caller follow a similar pattern. Meaning the variable names used in the caller are the same as the parameter names within the function.</p>
<p>EX:</p>
<pre><code>function myFunction(firstName, age, isCool, isHungry, isSleeping, isHappy) {}

<span class="hljs-comment">//**</span>

<span class="hljs-variable"><span class="hljs-keyword">var</span> firstName</span> = <span class="hljs-string">"val1"</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> age</span> = <span class="hljs-number">1</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> isCool</span> = <span class="hljs-literal">true</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> isHungry</span> = <span class="hljs-literal">false</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> isSleeping</span> = <span class="hljs-literal">false</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> isHappy</span> = <span class="hljs-literal">true</span>;
myFunction(firstName, age, isCool, isHungry, isSleeping, isHappy);
</code></pre>
<p>To refactor this we can simply have the caller pass an object, and have the function use destructuring of that object. It simply becomes.</p>
<pre><code>function myFunction({firstName, age, isCool, isHungry, isSleeping, isHappy}) {}
<span class="hljs-variable"><span class="hljs-keyword">var</span> firstName</span> = <span class="hljs-string">"val1"</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> age</span> = <span class="hljs-number">1</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> isCool</span> = <span class="hljs-literal">true</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> isHungry</span> = <span class="hljs-literal">false</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> isSleeping</span> = <span class="hljs-literal">false</span>;
<span class="hljs-variable"><span class="hljs-keyword">var</span> isHappy</span> = <span class="hljs-literal">true</span>;
myFunction({firstName, age, isCool, isHungry, isSleeping, isHappy});
</code></pre>
<p>This is cool because it's simple, requires very little work, and now we can gain the benefits of using an object instead of an ordered set of parameters.</p>
<p>This opens the door to quit a few other organization options.</p>
<p>Happy Cleanup!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Using script=module to Quicky Spike Some Mocha Tests]]></title>
        <id>https://staxmanade.com/2018/08/using-script-module-to-quicky-spike-some-mocha-tests/</id>
        <link href="https://staxmanade.com/2018/08/using-script-module-to-quicky-spike-some-mocha-tests/">
        </link>
        <updated>2018-08-03T21:42:53.703Z</updated>
        <summary type="html"><![CDATA[I'll be honest, I secretly hoped JSPM would win the front end over and become our standard, and while I haven't truly followed it closely in the last ...]]></summary>
        <content type="html"><![CDATA[<p>I'll be honest, I secretly hoped JSPM would win the front end over and become our standard, and while I haven't truly followed it closely in the last year or so I recently tried this out and was blown away at how beautifully simple it is (at least on the surface).</p>
<p>Say I want to quickly run some Mocha test in a browser. Like say I'm spiking something, wanting to use tests in something like jsbin or plunkr and just get code running quickly.</p>
<p>Most browsers now <a href="https://caniuse.com/#feat=es6-module">support tye script=module</a> tag which allows you to use <code>import</code> statements withing browser script tags. O_O</p>
<p>So how could I use this to <code>import mocha</code> and write some quick tests? I'm so glad you asked.</p>
<ol>
<li>Mocha's browser U.I. looks for an element with <code>id=mocha</code> so let's add that.</li>
</ol>
<pre><code class="language-diff">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;body&gt;
<span class="hljs-addition">+  &lt;div id="mocha"&gt;&lt;/div&gt;</span>
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<ol start="2">
<li>now let's add some javascript to import mocha</li>
</ol>
<pre><code class="language-diff">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;body&gt;
  &lt;div id="mocha"&gt;&lt;/div&gt;
<span class="hljs-addition">+  &lt;script type="module"&gt;</span>
<span class="hljs-addition">+    import "https://dev.jspm.io/mocha"</span>
<span class="hljs-addition">+    console.log("Mocha:", Mocha);</span>
<span class="hljs-addition">+  &lt;/script&gt;</span>
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>This package is loaded using the <code>import</code> functionality built into our browsers now and JSPM which allows us to load some <code>npm</code> packages right through the browser. MAGIC!</p>
<blockquote>
<p>WARNING: DO NOT do this for a production-type environment. This is just a quick prototype tool leveraging JSPM's dev hosted servers that allow us to use import to load packages via NPM through their servers. Thank you JSPM.</p>
</blockquote>
<ol start="3">
<li>Now we can do some browser-specific steps to get mocha to run.</li>
</ol>
<pre><code class="language-diff">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;body&gt;
  &lt;div id="mocha"&gt;&lt;/div&gt;
  &lt;script type="module"&gt;
    import "https://dev.jspm.io/mocha"
<span class="hljs-deletion">-    console.log("Mocha:", Mocha);</span>
<span class="hljs-addition">+    mocha.setup('bdd');</span>
<span class="hljs-addition">+</span>
<span class="hljs-addition">+    mocha.run();</span>
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<ol start="4">
<li>Let's add some tests.</li>
</ol>
<pre><code class="language-diff">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;body&gt;
  &lt;div id="mocha"&gt;&lt;/div&gt;
  &lt;script type="module"&gt;
    import "https://dev.jspm.io/mocha"
    mocha.setup('bdd');

<span class="hljs-addition">+    describe("some awesome tests", function () {</span>
<span class="hljs-addition">+        it("Should pass", function (){</span>
<span class="hljs-addition">+            console.log("passing test");</span>
<span class="hljs-addition">+        });</span>
<span class="hljs-addition">+        it("Should fail", function (){</span>
<span class="hljs-addition">+            throw new Error("OH NO!!!");</span>
<span class="hljs-addition">+        });</span>
<span class="hljs-addition">+    });</span>

    mocha.run();
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>THAT'S IT - using almost nothing but our browser's capabilities (and maybe a complicated JSPM back-end tool) we can easily write some in-browser tests to spike something, or just play around.</p>
<ol start="5">
<li>But wait - this looks like meh</li>
</ol>
<p>That's true, let's bring in some styles</p>
<pre><code class="language-diff">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;body&gt;
  &lt;div id="mocha"&gt;&lt;/div&gt;
<span class="hljs-addition">+  &lt;link rel="stylesheet" href="https://dev.jspm.io/mocha/mocha.css"&gt;</span>
  &lt;script type="module"&gt;
    import "https://dev.jspm.io/mocha"
    mocha.setup('bdd');

    describe("some awesome tests", function () {
        it("Should pass", function (){
            console.log("passing test");
        });
        it("Should fail", function (){
            throw new Error("OH NO!!!");
        });
    });

    mocha.run();
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<blockquote>
<p>NOTE: Prob better to use a CDN version instead of pounding JSPM servers (sorry).</p>
</blockquote>
<h1>Final</h1>
<pre><code>
<span class="hljs-doctype">&lt;!DOCTYPE html&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-title">body</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-title">div</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"mocha"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-title">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-title">link</span> <span class="hljs-attribute">rel</span>=<span class="hljs-value">"stylesheet"</span> <span class="hljs-attribute">href</span>=<span class="hljs-value">"https://dev.jspm.io/mocha/mocha.css"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-title">script</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"module"</span>&gt;</span><span class="javascript">
    <span class="hljs-keyword">import</span> <span class="hljs-string">"https://dev.jspm.io/mocha"</span>
    mocha.setup(<span class="hljs-string">'bdd'</span>);

    describe(<span class="hljs-string">"some awesome tests"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        it(<span class="hljs-string">"Should pass"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>)</span>{
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"passing test"</span>);
        });
        it(<span class="hljs-string">"Should fail"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>)</span>{
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"OH NO!!!"</span>);
        });
    });

    mocha.run();
  </span><span class="hljs-tag">&lt;/<span class="hljs-title">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-title">html</span>&gt;</span>
</code></pre>
<p>Cake!</p>
<p>I've done this a few times lately, and am almost able to do it without looking up api and syntax O_O. I also don't need webpack, gulp, servers, or anything but a wee-bit of html/js and some luck (that JSPM servers will hang in there).</p>
<p>Happy Testing!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[How to JSON.stringify and Order Dictionary Result]]></title>
        <id>https://staxmanade.com/2018/08/how-to-json.stringify-and-order-dictionary-result/</id>
        <link href="https://staxmanade.com/2018/08/how-to-json.stringify-and-order-dictionary-result/">
        </link>
        <updated>2018-08-02T02:14:57.050Z</updated>
        <summary type="html"><![CDATA[The other day I had the desire to serialize a simple Javascript Object and have it's keys ordered in the output.]]></summary>
        <content type="html"><![CDATA[<p>The other day I had the desire to serialize a simple Javascript Object and have it's keys ordered in the output.</p>
<p>Sorting before saving the object to a file like in <a href="https://github.com/approvals/Approvals.NodeJS">approvals</a> makes it much easier to diff two JSON documents that may not originally be in the same order.</p>
<p>So I threw together this quick little helper. It's far from perfect and won't suit all needs. But if all you're trying to do is sort and serialize an object it seems to be working well for now.</p>
<script src="https://gist.github.com/staxmanade/eddba7349cc6c5aed8c4389ce21a2fc4.js"></script>
<p>Happy Dictionary Reading!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Should I Use JavaScript Single (') or Double (") Quotes?]]></title>
        <id>https://staxmanade.com/2018/03/should-i-use-javascript-single-or-double-quotes/</id>
        <link href="https://staxmanade.com/2018/03/should-i-use-javascript-single-or-double-quotes/">
        </link>
        <updated>2018-03-16T06:00:00.000Z</updated>
        <summary type="html"><![CDATA[The topic of using JavaScript single `'` or double `"` quotes comes up often enough that I thought I'd create a bit of an amalgamation of items around...]]></summary>
        <content type="html"><![CDATA[<p>The topic of using JavaScript single <code>'</code> or double <code>&quot;</code> quotes comes up often enough that I thought I'd create a bit of an amalgamation of items around the topic for future reference.</p>
<p>Today, it came up at work when someone sent a PR to our internal standard <a href="https://eslint.org/">eslint</a> config repository and there were some various points brought up with no real final solid winner or resolution.</p>
<p>In this post, I'm not (sadly) going to write anything interesting or profound or even original. Just wanted to aggregate some pros/cons as I've seen splattered in various locations around the web on the topic.</p>
<h1>The most important point or the TL;DR</h1>
<ul>
<li>Define one standard and stick to it. Do not use one in one file, and a different one in another file, or even especially avoid mixing quotes within the same file if possible.</li>
</ul>
<h2>Basic qualities they both share</h2>
<ul>
<li>They both represent strings (yay! strings!)</li>
<li>Which ever one you start with, must be the same one you end the string with.</li>
<li>There is really no difference in the end between using single or double quotes, meaning they both represent a string in the end. The system doesn't really care which one you use (but you might?).</li>
<li>No need to escape the other character within a string. So a double quoted string can have single quotes without escaping them, and a single quoted string can have double quotes within it without having to escape them.
<ul>
<li><code>&quot;Double quotes with a single ( ' ) quote in the middle&quot;</code></li>
<li><code>'Single quotes with a double ( &quot; ) quote in the middle'</code></li>
</ul>
</li>
<li>Each type must escape their own type
<ul>
<li><code>&quot;double quotes ( \&quot; ) must escape a double quote&quot;</code></li>
<li><code>'single quotes ( \' ) must escape a single quote'</code></li>
</ul>
</li>
<li>On German, Hungarian, Austrian, and many other keyboards, you have to use the Shift key for both single or double quotes.</li>
<li>On Turkish Q keyboards it's apparently the other way around (need <code>&lt;Shift&gt;</code> for single quote vs double).</li>
</ul>
<h2>Pros for single quotes:</h2>
<ul>
<li>One popular argument for single quotes is when you have to write html within javascript:
<ul>
<li>If you use single quotes you can write <code>var html = '&lt;div id=&quot;some_div&quot;&gt;&lt;/div&gt;'</code></li>
<li>If you use double quotes you must escape each nested <code>&quot;</code> EX: <code>var html = &quot;&lt;div id=\&quot;some_div\&quot;&gt;&lt;/div&gt;&quot;</code> which can get annoying. Or you could use single quotes within the html string, but I don't want to cover quotes for html here (that would just hurt)...</li>
</ul>
</li>
<li>Single quotes can often look better when you're using them to represent an empty string <code>''</code> vs <code>&quot;&quot;</code> (too many little marks in the latter and can be difficult read - ahhh)</li>
</ul>
<h2>Cons for single quotes:</h2>
<p>Only real con I can come up with is copying/pasting between JSON and JavaScript files - single quotes are not supported within JSON files, so you'd have to do a host of search/replace (and escaping of double quotes)...</p>
<h2>Pros for double quotes:</h2>
<ul>
<li>JSON only allows double quotes (unless you control the data, and can use a library that is more liberal at parsing JSON - but a JSON file with single quotes is not truly a JSON file)</li>
<li>Most likely noobies to JS will be familiar with double quotes from their previous programming languages</li>
<li>Double quotes eliminate the need to escape apostrophes when writing english sentences.</li>
</ul>
<h2>Cons for Double quotes:</h2>
<ul>
<li>Must press an extra key <code>&lt;Shift&gt;</code> when wanting to use double quotes</li>
</ul>
<h1>In the end</h1>
<p>I recommend single quotes as a solid standard. Unless you are copying JSON objects in JavaScript and pasting them into JS files a ton - it's generally my personal preference.</p>
<h1>Some References:</h1>
<ul>
<li><a href="https://stackoverflow.com/questions/242813/when-to-use-double-or-single-quotes-in-javascript">https://stackoverflow.com/questions/242813/when-to-use-double-or-single-quotes-in-javascript</a></li>
<li><a href="https://stackoverflow.com/questions/9959928/double-quotes-vs-single-quotes-in-javascript">https://stackoverflow.com/questions/9959928/double-quotes-vs-single-quotes-in-javascript</a></li>
<li><a href="https://stackoverflow.com/questions/3149192/difference-between-single-quotes-and-double-quotes-in-javascript">https://stackoverflow.com/questions/3149192/difference-between-single-quotes-and-double-quotes-in-javascript</a></li>
<li><a href="https://plus.google.com/+DouglasCrockfordEsq/posts/EBky2K9erKt">https://plus.google.com/+DouglasCrockfordEsq/posts/EBky2K9erKt</a></li>
</ul>
<p>Happy Quoting!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[How to Access Two Mac Accounts at the Same Time]]></title>
        <id>https://staxmanade.com/2017/10/how-to-access-two-mac-accounts-at-the-same-time/</id>
        <link href="https://staxmanade.com/2017/10/how-to-access-two-mac-accounts-at-the-same-time/">
        </link>
        <updated>2017-10-09T15:55:51.649Z</updated>
        <summary type="html"><![CDATA[From a single Mac if you wanted to access two unique accounts at the same time, I found out through a [neat little trick](https://apple.stackexchange....]]></summary>
        <content type="html"><![CDATA[<p>From a single Mac if you wanted to access two unique accounts at the same time, I found out through a <a href="https://apple.stackexchange.com/a/151160">neat little trick</a> how to accomplish this.</p>
<p>This allows you to log in to a second unique Mac user while already being logged into the first account already. It can be done without having to logout/login to each one individually (one at a time).</p>
<h2>Why would I need to do this?</h2>
<p>The reasons could vary but here are a couple examples:</p>
<ul>
<li>If you use one user for work, and one for personal to keep some separate context, but while at work maybe need to access a file or email from the personal account.</li>
<li>You'd like to access a separate iMessage account without it getting mixed into yours. Say you want to spy on the kid. (Not saying whether this is ethical or not - depends on your parenting style - just proposing a reason for using this tool).</li>
</ul>
<h2>Disclaimer</h2>
<blockquote>
<p>To accomplish this we're going to be turning on some services/features that have the potential to open security vulnerabilities so please use with caution and learn/know your risks.</p>
</blockquote>
<h2>Setup/Configuration</h2>
<p>To accomplish this your Mac needs to have the proper permissions and configuration in place to allow this to happen.</p>
<p>First we need to access the system preferences:</p>
<p><img src="/images/posts/dual-login/access-preferences.png" alt="access mac system preferences"></p>
<p>Then open the <code>Sharing</code> preferences:</p>
<p><img src="/images/posts/dual-login/preferences-highlight-sharing.png" alt="mac sharing preferences"></p>
<p>Then enable <code>Screen Sharing</code> and don't forget to add the specific users you want to allow screen to be shared for.</p>
<blockquote>
<p>Note: I blocked out this specific user-name - but assume the blacked out user is the Mac account's user that I want to log into using the Screen Sharing application</p>
</blockquote>
<p><img src="/images/posts/dual-login/screen-sharing-preference.png" alt="screen sharing preference"></p>
<p>I had to enable enable remote login to allow the up-coming <code>ssh</code> command to run. Here is the configuration I used:</p>
<p><img src="/images/posts/dual-login/remote-login.png" alt="remote login preference"></p>
<h2>Startup an SSH Session</h2>
<p>From the currently logged in session, open a <code>Terminal</code> and run the following command:</p>
<pre><code>ssh -NL <span class="hljs-number">5901</span>:localhost:<span class="hljs-number">5900</span> localhost
</code></pre>
<p>The <code>-L</code> has this to say in ssh's man pages</p>
<pre><code>     -L [bind_address:]port:host:hostport
     -L [bind_address:]port:remote_socket
     -L local_socket:host:hostport
     -L local_socket:remote_socket
             Specifies <span class="hljs-keyword">that</span> connections <span class="hljs-keyword">to</span> <span class="hljs-keyword">the</span> <span class="hljs-keyword">given</span> TCP port <span class="hljs-keyword">or</span> Unix socket <span class="hljs-function_start"><span class="hljs-keyword">on</span></span> <span class="hljs-keyword">the</span> <span class="hljs-keyword">local</span> (client) host are <span class="hljs-keyword">to</span> be forwarded <span class="hljs-keyword">to</span> <span class="hljs-keyword">the</span>
             <span class="hljs-keyword">given</span> host <span class="hljs-keyword">and</span> port, <span class="hljs-keyword">or</span> Unix socket, <span class="hljs-function_start"><span class="hljs-keyword">on</span></span> <span class="hljs-keyword">the</span> remote side.  This works <span class="hljs-keyword">by</span> allocating a socket <span class="hljs-keyword">to</span> listen <span class="hljs-keyword">to</span> either a TCP port
             <span class="hljs-function_start"><span class="hljs-keyword">on</span></span> <span class="hljs-keyword">the</span> <span class="hljs-keyword">local</span> side, optionally bound <span class="hljs-keyword">to</span> <span class="hljs-keyword">the</span> specified bind_address, <span class="hljs-keyword">or</span> <span class="hljs-keyword">to</span> a Unix socket.  Whenever a connection <span class="hljs-keyword">is</span> made <span class="hljs-keyword">to</span>
             <span class="hljs-keyword">the</span> <span class="hljs-keyword">local</span> port <span class="hljs-keyword">or</span> socket, <span class="hljs-keyword">the</span> connection <span class="hljs-keyword">is</span> forwarded <span class="hljs-keyword">over</span> <span class="hljs-keyword">the</span> secure channel, <span class="hljs-keyword">and</span> a connection <span class="hljs-keyword">is</span> made <span class="hljs-keyword">to</span> either host
             port hostport, <span class="hljs-keyword">or</span> <span class="hljs-keyword">the</span> Unix socket remote_socket, <span class="hljs-keyword">from</span> <span class="hljs-keyword">the</span> remote machine.

             Port forwardings can also be specified <span class="hljs-keyword">in</span> <span class="hljs-keyword">the</span> configuration <span class="hljs-type">file</span>.  Only <span class="hljs-keyword">the</span> superuser can forward privileged ports.  IPv6
             addresses can be specified <span class="hljs-keyword">by</span> enclosing <span class="hljs-keyword">the</span> address <span class="hljs-keyword">in</span> square brackets.

             By default, <span class="hljs-keyword">the</span> <span class="hljs-keyword">local</span> port <span class="hljs-keyword">is</span> bound <span class="hljs-keyword">in</span> accordance <span class="hljs-keyword">with</span> <span class="hljs-keyword">the</span> GatewayPorts setting.  However, an explicit bind_address may be
             used <span class="hljs-keyword">to</span> bind <span class="hljs-keyword">the</span> connection <span class="hljs-keyword">to</span> a specific address.  The bind_address <span class="hljs-keyword">of</span> ``localhost'' indicates <span class="hljs-keyword">that</span> <span class="hljs-keyword">the</span> listening port be
             bound <span class="hljs-keyword">for</span> <span class="hljs-keyword">local</span> use only, <span class="hljs-keyword">while</span> an empty address <span class="hljs-keyword">or</span> `*' indicates <span class="hljs-keyword">that</span> <span class="hljs-keyword">the</span> port should be available <span class="hljs-keyword">from</span> all interfaces.
</code></pre>
<p>For <code>-N</code>:</p>
<pre><code>     -N      <span class="hljs-operator"><span class="hljs-keyword">Do</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">execute</span> a remote command.  This <span class="hljs-keyword">is</span> useful <span class="hljs-keyword">for</span> just forwarding ports.
</span></code></pre>
<p>Here's what it looks like when I ran it locally:</p>
<pre><code>&gt; ssh -NL <span class="hljs-number">5901</span>:localhost:<span class="hljs-number">5900</span> localhost
The authenticity <span class="hljs-keyword">of</span> host 'localhost (::<span class="hljs-number">1</span>)' can't be established.
ECDSA key fingerprint <span class="hljs-keyword">is</span> SHA256:ytfRv5WDPuTjGbBugJjmc8gOhsHga7ozGqNgjOXpdRM.
Are you sure you want <span class="hljs-keyword">to</span> <span class="hljs-keyword">continue</span> connecting (yes/no)? yes
Warning: Permanently added 'localhost' (ECDSA) <span class="hljs-keyword">to</span> <span class="hljs-keyword">the</span> <span class="hljs-type">list</span> <span class="hljs-keyword">of</span> known hosts.
Password: &lt;I entered <span class="hljs-keyword">my</span> account/admin password&gt;
</code></pre>
<h2>Use Screen Sharing to login</h2>
<p>Once that ssh command above is up and running, we're now ready to log into the other account using Screen Sharing.</p>
<p>Open the <code>Screen Sharing</code> Mac app located in: <code>/System/Library/CoreServices/Screen Sharing.app</code>. You can also use <code>CMD+&lt;Space&gt;</code> (Spotlight) and type <code>Screen Sharing</code> to open the app.</p>
<p>Then enter <code>localhost:5901</code> to start the process.</p>
<p>It should look like this:</p>
<p><img src="/images/posts/dual-login/screen-sharing-startup.png" alt="screen sharing app startup view"></p>
<p>In the below screen entered the username/password that you want to login as. (Not the current account - the other one)</p>
<p><img src="/images/posts/dual-login/screen-sharing-login.png" alt="screen sharing app login view"></p>
<p>Now select that you want to login as &quot;yourself&quot; where &quot;yourself&quot; is really &quot;other account&quot;:</p>
<p><img src="/images/posts/dual-login/screen-sharing-select-user.png" alt="screen sharing app access user strategy view"></p>
<p>...and boom, you should now able to use two separate accounts on a single Mac session.</p>
<p>Happy Spying (wink wink)!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[How to block git commit if webpack bundle has changed]]></title>
        <id>https://staxmanade.com/2017/06/how-to-block-git-commit-if-webpack-bundle-has-changed/</id>
        <link href="https://staxmanade.com/2017/06/how-to-block-git-commit-if-webpack-bundle-has-changed/">
        </link>
        <updated>2017-06-01T21:58:03.582Z</updated>
        <summary type="html"><![CDATA[I sometimes write little web app utilities that are often statically hosted. But to use some of the new ES features means I need to drop in a build pr...]]></summary>
        <content type="html"><![CDATA[<p>I sometimes write little web app utilities that are often statically hosted. But to use some of the new ES features means I need to drop in a build process that creates a bundle before the code gets checked in.</p>
<p>There are two parts to this.</p>
<ol>
<li>The raw source code. The ES6+7+next and all the nifty new js features I want to leverage today.</li>
<li>The bundled es5 output.</li>
</ol>
<p>In some of these projects it means I also check in the bundled code into git. A common use case is to be able to use github's pages feature to host this content (err bundled output) as well as the raw source.</p>
<p>The problem we can run into is if you make a change to the source, commit and push - nothing happened... Because the bundled code didn't get re-bundled, the github hosted pages page doesn't pull the latest changes in.</p>
<p>I'm a <a href="https://staxmanade.com/2014/03/rake-psake-grunt-gulp-jake-make-cake/">fan of using</a> git <a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks">pre-commit hooks</a> to catch you early in the development life cycle to on things like test errors (or in this case a bundle issues).</p>
<p>So I came up with an example that allows me to make code changes and catch myself from committing when the raw source has changed, but the bundle did not reflect that.</p>
<h1>So what is this thing?</h1>
<p>The gist is it's a <code>.js</code> script that runs a set of actions and tests for the bundle.js currently vs what's about to be committed. Failing to commit if the current bundle doesn't match what the previous bundle is... Meaning, when we run our build (webpack in this case) if the bundle.js didn't change, we can commit.</p>
<p>This ensures that whatever bundle.js is committed is tied to the code-change the original source. Avoiding &quot;fixing&quot; something in the source and it not actually getting deployed because the bundle is out of date.</p>
<h1>First get a pre-commit tool</h1>
<p>There are some good options in the npm/node world for pre-commit hooks. Check out <a href="https://github.com/typicode/husky">husky</a> or <a href="https://github.com/observing/pre-commit">pre-commit</a>. However you get your precommit hook setup - great...</p>
<p>In my case I used <code>husky</code> and here are the relevant bits to my <code>package.json</code>.</p>
<pre><code class="language-diff">{
  ...

  "devDependencies": {
<span class="hljs-addition">+    "husky": "^0.13.4"</span>
  }
  "scripts": {
<span class="hljs-addition">+    "precommit": "node ./pre-commit-build.js"</span>
  }
}
</code></pre>
<h1>The <code>pre-commit-build.js</code> script I used</h1>
<p>The below is the short, but complete pre-commit script I use to enforce this workflow.</p>
<pre><code class="language-javascript"><span class="hljs-keyword">var</span> crypto = <span class="hljs-built_in">require</span>(<span class="hljs-string">'crypto'</span>);
<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
<span class="hljs-keyword">var</span> exec = <span class="hljs-built_in">require</span>(<span class="hljs-string">'child_process'</span>).exec;

<span class="hljs-keyword">var</span> bundleFileName = <span class="hljs-string">'./dist/bundle.js'</span>;

<span class="hljs-keyword">var</span> getShaOfBundle = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> distFile = fs.readFileSync(bundleFileName);
    <span class="hljs-keyword">var</span> sha = crypto.createHash(<span class="hljs-string">'sha1'</span>).update(distFile).digest(<span class="hljs-string">"hex"</span>);
    <span class="hljs-keyword">return</span> sha;
}

<span class="hljs-comment">// make sure we only bundle/build what is staged to get a proper</span>
<span class="hljs-comment">// view of what will be committed</span>
exec(<span class="hljs-string">'git stash --keep-index'</span>);

<span class="hljs-comment">// Get a snapshot of the original bundle</span>
<span class="hljs-keyword">var</span> beforeSha = getShaOfBundle();

<span class="hljs-comment">// run our build</span>
exec(<span class="hljs-string">'./node_modules/.bin/webpack'</span>);

<span class="hljs-comment">// snapshot the bundle after the build</span>
<span class="hljs-keyword">var</span> afterSha = getShaOfBundle();

<span class="hljs-comment">// reset anything that was stashed</span>
exec(<span class="hljs-string">'git stash pop'</span>);

<span class="hljs-keyword">if</span> (beforeSha !== afterSha) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Need to bundle before committing"</span>);
}
</code></pre>
<p>Now whenever I make a change to the raw source code - this pre-commit script makes sure that the <code>dist/bundle.js</code> is correctly mapped to the raw source.</p>
<p>Happy committing!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[How to Download and Convert an Image to Base64 Data Url]]></title>
        <id>https://staxmanade.com/2017/02/how-to-download-and-convert-an-image-to-base64-data-url/</id>
        <link href="https://staxmanade.com/2017/02/how-to-download-and-convert-an-image-to-base64-data-url/">
        </link>
        <updated>2017-02-27T05:06:20.088Z</updated>
        <summary type="html"><![CDATA[Today I was playing around with a side-oss-project and had the desire to take an image from the web and base64 data encode it. While I'm sure there is...]]></summary>
        <content type="html"><![CDATA[<p>Today I was playing around with a side-oss-project and had the desire to take an image from the web and base64 data encode it. While I'm sure there is a ton written out there, I didn't immediately find the specific steps in a snippet of code. (Also, I can't say I looked very hard).</p>
<p>So what does any programmer do when he's not satisfied with what he can't find? He writes his own. Now that I've put it together I'm just going to post this here so I can find it again down the road when I need to. :)</p>
<p>Below is a utility function that I threw together that will take an <code>imageUrl</code> parameter and will return through a Promise a base64 encoded image data string. You can see from the example usage below that we're just setting an HTML image <code>.src</code> property to the result of this function and it should just work.</p>
<blockquote>
<p>NOTE: also if you look at the code that accomplish this below, it may look a bit like &quot;futuristic&quot; JavaScript right now. With all the <code>async/await</code>, <code>arrow functions</code>, <code>http fetch</code> and all, but the cool thing is you should be able to just copy/paste the below into a JSBin/Plnkr/Codepen without issue (in Chrome). No need for Babel/TypeScript/transpiler if you're just prototyping something (as I was). Don't rely on this to work in all browsers yet but I'm sure when I'll be googling myself for this snippet in the future, this should work in most browsers so I'll just leave this here for now.</p>
</blockquote>
<pre><code><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getBase64ImageFromUrl</span>(<span class="hljs-params">imageUrl</span>) </span>{
  <span class="hljs-keyword">var</span> res = <span class="hljs-keyword">await</span> fetch(imageUrl);
  <span class="hljs-keyword">var</span> blob = <span class="hljs-keyword">await</span> res.blob();

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>((resolve, reject) =&gt; {
    <span class="hljs-keyword">var</span> reader  = <span class="hljs-keyword">new</span> FileReader();
    reader.addEventListener(<span class="hljs-string">"load"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        resolve(reader.result);
    }, <span class="hljs-literal">false</span>);

    reader.onerror = () =&gt; {
      <span class="hljs-keyword">return</span> reject(<span class="hljs-keyword">this</span>);
    };
    reader.readAsDataURL(blob);
  })
}
</code></pre>
<p>An example usage of the above:</p>
<pre><code>getBase64ImageFromUrl('http://approvaltests.com/images/logo.png')
    .then(<span class="hljs-literal">result</span> =&gt; testImage.src = <span class="hljs-literal">result</span>)
    .catch(err =&gt; console.error(err));
</code></pre>
<p>As an alternative to base64 encoded <a href="https://developer.mozilla.org/en-US/docs/Web/API/FileReader">FileReader</a> approach above, you can also also use the <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL">URL.createObjectURL</a> <code>return URL.createObjectURL(blob);</code></p>
<p>There's of course a number of <a href="http://lmgtfy.com/?q=convert+image+to+base64+online+tool">online tools</a> that do this for you already.</p>
<p>Hope this helps future me find the implementation a min or two faster some day.</p>
<p>Happy Encoding!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Porting a Large JSPM BabelJS project to Typescript]]></title>
        <id>https://staxmanade.com/2017/02/porting-a-large-jspm-babeljs-project-to-typescript/</id>
        <link href="https://staxmanade.com/2017/02/porting-a-large-jspm-babeljs-project-to-typescript/">
        </link>
        <updated>2017-02-20T06:33:46.360Z</updated>
        <summary type="html"><![CDATA[I've been working on a project for over a year now that was originally written in ES6 with (some async/await ES7) using [BabelJS](https://babeljs.io/)...]]></summary>
        <content type="html"><![CDATA[<p>I've been working on a project for over a year now that was originally written in ES6 with (some async/await ES7) using <a href="https://babeljs.io/">BabelJS</a> to transpile and really enjoying the experience of using the latest javascript.</p>
<p>ES6/7 was great at the beginning, when I had 1, then 2... then 5 files. The project was small, I could pretty much load the entire application into my own head at once, reason, tweak, plow forward.</p>
<p>It didn't take too long before the project grew beyond a single load into memory. Now I'm mentally paging out components from different files as I work on various sections of the application.</p>
<p>Just like anything, once the project grew to this point, it became a little more difficult to maintain. Now, I consider myself a <a href="https://staxmanade.com/2015/08/habit-of-a-solid-developer-introduction/">fairly solid developer</a>, and that's likely how I made it this far without a compiler as my components were small, surface areas tight and the interactions between them were well managed. I also had a decent number of <a href="https://staxmanade.com/2015/03/in-app-unit-tests/">in-app unit and integration tests</a> because generally (but not always) I'm a <a href="https://staxmanade.com/2012/01/you-are-responsible-for-making-that/">test-first kind of guy</a>.</p>
<p>However, that didn't stop me from breaking things, making mistakes or just out-right screwing up a javascript file here and there along the way.</p>
<p>While working on this project, it always niggled me that the project would keep growing without the ability for the most basic of unit-tests to run (the compiler). Almost a year ago I even remember trying to use Typescript but using it with JSPM and without having VisualStudio Code all together, it just never came together (or I just didn't try hard enough).</p>
<p>But this past week, I gave it another go, and while I'm not totally there (or where I'd like to end up), I'm quite happy with the results I've made so far and am impressed and quite happily working in a project that has completely been ported to Typescript from ES6/7 using BabelJS.</p>
<h1>First some idea about the project.</h1>
<p>Now, when it comes to large software projects, I'm pretty sure I shouldn't be calling this project a &quot;large&quot; as the subject of this post seems to label it... But for a system built only by me in some nights and weekends, it is the largest single app I've built alone, so that's where I'm defining &quot;Large&quot;.</p>
<p>The project has just about a hundred javascript files/components/classes/modules and comes in just above <code>12,000</code> lines of code. That's not counting of course all the dependencies pulled in through JSPM (using both NPM and Github). In fact I really need to look at my dependencies and see where I can trim some fat, but that's not the subject of this post.</p>
<h1>Porting from Babel to TypeScript</h1>
<p>With some context about the project this is coming from out of the way, I thought it would be helpful to outline the steps (or stumbles) I took along the way to get my project up and running using TypeScript with JSPM.</p>
<h1>Pre-migration steps</h1>
<p>Below are steps I took to get this thing going. I doubt they're perfect or even apply to your or anyone elses projects, but here's hoping they're helpful</p>
<ol>
<li>In a fresh temp folder, I used the <code>jspm init</code> command to setup a fresh new project and selected the <code>Typescript</code> transpiler option.</li>
</ol>
<blockquote>
<p>this allowed me to inspect what a &quot;fresh&quot; project from JSPM would look like with Typescript setup.</p>
</blockquote>
<ol start="2">
<li>The next thing I did was review the angular getting started guide to see what Typescript specific configurations they used.</li>
</ol>
<blockquote>
<p>Now, my project isn't Angular (it's actually React based), but I thought I could learn a little something along the way. I don't know if I actually gleaned anything while doing this (as I'm writing this post a ways after I actually did the work, but as an FYI, you might learn something reading it)</p>
</blockquote>
<h1>What steps did I take to port the project?</h1>
<p>Looking back at the series of commits during my port, here's basically what I did. In some cases order doesn't matter below, but I left this list in the order of my projects git commit log.</p>
<ol>
<li>Renaming each file with the <code>.jsx</code> extension to <code>.tsx</code> (Typescript's variant of JSX) (note: not renaming anything but code I wrote - so don't touch anything in <code>jspm_packages</code> or <code>node_modules</code> folders etc.</li>
<li><code>jspm install ts</code> &lt;-- installing the <a href="https://github.com/frankwallis/plugin-Typescript">Typescript jspm plugin</a></li>
<li>Updated my <code>jspm.config.js</code> <code>transpiler</code> flag with the following:</li>
</ol>
<pre><code class="language-diff"><span class="hljs-deletion">-  transpiler: "plugin-babel",</span>
<span class="hljs-addition">+  transpiler: "Typescript",</span>
<span class="hljs-addition">+  TypescriptOptions: {</span>
<span class="hljs-addition">+    "tsconfig": true // indicates that a tsconfig exists that should be used</span>
<span class="hljs-addition">+  },</span>
</code></pre>
<p>Then I updated my <code>jspm.config.js</code>'s <code>app</code> section with the following.</p>
<pre><code class="language-diff">   packages: {
<span class="hljs-deletion">-    "app": {</span>
<span class="hljs-deletion">-      "defaultExtension": false,</span>
<span class="hljs-deletion">-      "main": "bootstrap.jsx",</span>
<span class="hljs-deletion">-       "meta": {</span>
<span class="hljs-deletion">-        "*": {</span>
<span class="hljs-deletion">-          "babelOptions": {</span>
<span class="hljs-deletion">-            "plugins": [</span>
<span class="hljs-deletion">-              "babel-plugin-transform-react-jsx",</span>
<span class="hljs-deletion">-              "babel-plugin-transform-decorators-legacy"</span>
<span class="hljs-deletion">-            ]</span>
<span class="hljs-deletion">-          }</span>
<span class="hljs-deletion">-        }</span>
<span class="hljs-deletion">-      }</span>
<span class="hljs-deletion">-    },</span>
<span class="hljs-addition">+    "app": { // all files within the app folder</span>
<span class="hljs-addition">+      "main": "bootstrap.tsx", // main file of the package (will be important later)</span>
<span class="hljs-addition">+      "format": "system", // module format</span>
<span class="hljs-addition">+      "defaultExtension": "ts", // default extension of all files</span>
<span class="hljs-addition">+      "meta": {</span>
<span class="hljs-addition">+        "*.ts": { // all ts files will be loaded with the ts loader</span>
<span class="hljs-addition">+          "loader": "ts"</span>
<span class="hljs-addition">+        },</span>
<span class="hljs-addition">+        "*.tsx": { // all ts files will be loaded with the ts loader</span>
<span class="hljs-addition">+          "loader": "ts"</span>
<span class="hljs-addition">+        },</span>
<span class="hljs-addition">+      }</span>
<span class="hljs-addition">+    },</span>
</code></pre>
<ol start="4">
<li>Created a <code>tsconfig.json</code> file</li>
</ol>
<pre><code class="language-javascript">{
 <span class="hljs-string">"compilerOptions"</span>: {
    <span class="hljs-string">"target"</span>: <span class="hljs-string">"es5"</span>,                <span class="hljs-comment">/* target of the compilation (es5) */</span>
    <span class="hljs-string">"module"</span>: <span class="hljs-string">"system"</span>,             <span class="hljs-comment">/* System.register([dependencies], function) (in JS)*/</span>
    <span class="hljs-string">"moduleResolution"</span>: <span class="hljs-string">"node"</span>,     <span class="hljs-comment">/* how module gets resolved (needed for Angular 2)*/</span>
    <span class="hljs-string">"emitDecoratorMetadata"</span>: <span class="hljs-literal">true</span>,  <span class="hljs-comment">/* needed for decorators */</span>
    <span class="hljs-string">"experimentalDecorators"</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">/* needed for decorators (@Injectable) */</span>
    <span class="hljs-string">"noImplicitAny"</span>: <span class="hljs-literal">false</span>,         <span class="hljs-comment">/* any has to be written explicitly*/</span>
    <span class="hljs-string">"jsx"</span>: <span class="hljs-string">"react"</span>
  },
  <span class="hljs-string">"exclude"</span>: [   <span class="hljs-comment">/* since compiling these packages could take ages, we want to ignore them*/</span>
    <span class="hljs-string">"jspm_packages"</span>,
    <span class="hljs-string">"node_modules"</span>
  ],
  <span class="hljs-string">"compileOnSave"</span>: <span class="hljs-literal">false</span>        <span class="hljs-comment">/* on default the compiler will create js files */</span>
</code></pre>
<ol start="5">
<li>Renamed <code>*.js</code> files to <code>*.ts</code>. (Similar to step 1 above with <code>jsx -&gt; tsx</code> but now just the plain JavaScript files)</li>
<li>In all of my source code where I used to do this: <code>import foo from './foo.js'</code> I removed the <code>.js</code> extensions like <code>import foo from './foo'</code></li>
<li>I did NOT remove the <code>.jsx</code> extension in my <code>import</code> statements - but renamed them to <code>tsx</code> so <code>import foo from './foo.jsx'</code> became <code>import foo from './foo.tjs'</code></li>
<li>Next I added a file at the root of my client project called <code>globalTypes.d.ts</code>, this is where I could hack in some type definitions that I use globally in the project.</li>
<li>Then I started adding my type definitions...</li>
</ol>
<p>I used the <a href="https://github.com/typings/typings">typings</a> tool to search for TypeScript type definitions. And if I found one, I would typically try to install them from <code>npm</code>.</p>
<p>For example: searching for <code>react</code> like <code>typings search react</code> shows me that there is a DefinitelyTyped version of the type defs and <a href="https://blogs.msdn.microsoft.com/Typescript/2016/06/15/the-future-of-declaration-files/">I now know</a> that we can use NPM to install them by typing <code>npm install --save @types/react</code></p>
<p>So I installed a ton of external library typings.</p>
<ol start="11">
<li>Next, started looking around my editor <a href="https://code.visualstudio.com/">VisualStudio Code</a> in hopes to see a bunch of typing errors reported, and was surprised to see very few. No, not because I'm so good at JavaScript that my TypeScript was perfect. Far from it... The problem I had was the <code>tsconfig.json</code> file was not at the root of my project (was at the root of my client site) - but it was nested several folders down from the root of my project. For some reason the editor wasn't picking it up until I opened the editor from the location the <code>tsconfig.json</code> file was rooted, things didn't work.</li>
</ol>
<blockquote>
<p>Honestly, I don't know what the above was about - but was something I ran into. I can't say for certain if it is still an issue - I think I'm starting to see editor features load up regardless of what folder I open things - so your mileage may vary.</p>
</blockquote>
<ol start="12">
<li>Once the TypeScript editor features started lighting up in VS Code, my next steps were start to take the TypeScript's feedback and implement either typing work-arounds or fixing actual bugs the compiler found.</li>
</ol>
<p>THE END - ish</p>
<h1>Where am I now?</h1>
<p>The above steps were really all I went through to port this project over to TypeScript and it was relatively seamless. That's not to say it was simple or easy, but definitely do-able, and worth it.</p>
<p>It's been a few weeks since I ported the project to TypeScript and I'm really kicking myself for not doing it sooner.</p>
<p>The editor assist with intellisense of function calls from internal and external modules and their usage/function signatures saves time researching external documentation.</p>
<h1>Other observations since the move.</h1>
<ol>
<li>Builds seem to be a little faster with TypeScript than Babel. I can't say I can prove this. I didn't do any actual tests on this, but just a feeling I got after migration.</li>
<li>Sourcemaps seem to actually work. Whenever I used BabelJS, debugging and stepping through async/await it just never seemed to line up right for me. This was likely user-error or in-proper configuration of babel on my part, so who knows... but having working source-maps is AMAZING, especially with the <code>async/await</code> feature.</li>
<li>One area of concern that I haven't yet worked through. Is the JSPM typescript loading up in the browser - or running <code>jspm bundle app</code> at the command line doesn't report any typescript errors - or fail any builds. However, I'm glad it doesn't because something isn't quite rite with my configuration as every import of a <code>.tsx</code> file reports an error. So, for now I'm just relying on the red squigglies in my VS Code editor to help me catch typing errors.</li>
</ol>
<p>If you go for this port in your own project, I hope this was helpful, and that your port goes well.</p>
<p>Happy TypeScripting!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[TVJS TVHelpers DirectionalNavigation and Adapting/Hacking some WinJS Focus Management]]></title>
        <id>https://staxmanade.com/2016/12/tvjs-tvhelpers-directionalnavigation-and-adapting-hacking-some-winjs-focus-management/</id>
        <link href="https://staxmanade.com/2016/12/tvjs-tvhelpers-directionalnavigation-and-adapting-hacking-some-winjs-focus-management/">
        </link>
        <updated>2016-12-20T06:17:05.148Z</updated>
        <summary type="html"><![CDATA[So, Microsoft created what really turned out to be an amazing set of HTML/JS/CSS controls when they released the WinJS library. Not to go too much int...]]></summary>
        <content type="html"><![CDATA[<p>So, Microsoft created what really turned out to be an amazing set of HTML/JS/CSS controls when they released the WinJS library. Not to go too much into the history, but honestly I hated it when I first had to use it. But, let me clarify. It wasn't until this last year when I learned that I didn't hate the WinJS controls by themselves, but I despised the way you declared their usage using the specialized <code>win-*</code> html attributes. It felt like a total hack to get an app up and running by littering semantic html with these attributes.</p>
<p>Then along comes a little toy project they created called <a href="https://github.com/winjs/react-winjs">react-winjs</a> and all of a sudden the <code>WinJS</code> &quot;Components&quot; made total sense. When looking at them through the lense of WinJS through ReactJS components was the first time that I not only clicked with WinJS, but I actually fell in lov... (well I won't go that far), but was excited enough about them to pick them as the primary U.I. control suite while building out a little side-project.</p>
<p>Fast forward a year of development, and Microsoft essentially <a href="https://github.com/winjs/winjs#status">bailed on WinJS</a> but at least they left it out in the open so I could hack on it and continue to depend on <a href="https://github.com/staxmanade/winjs-self-built">my own fork</a> for the time being.</p>
<p>Then, they announce a <a href="https://github.com/Microsoft/TVHelpers/">NEW &amp; SHINY</a> library that can be used to help develop UWP and TV/Xbox One apps which is great. Except, WinJS doesn't work with this new library out-of-the-box, and since Microsoft isn't adding new features to WinJS, they likely never will build-in compatibility with the new &amp; shiny library.</p>
<p>Guess that means we (I) have to figure it out on my own. And although I write this knowing that I'm probably the ONLY developer on the planet using this combination of libraries, I wanted to put out some of the hacks/code I've thrown together to get some WinJS controls to play nice with TVJS with regards to focus management.</p>
<h2>What is focus management you say?</h2>
<p>In the context of an Xbox app, the idea is to take your'e web-page-app and get rid of the ugly mouse-like-cursor you'd see if you didn't do this and replace it with a controller navigable approach - so up/down/left/right on the controller moves the visible &quot;focus&quot; around the application and the <code>A</code> button &quot;presses enter&quot; (or invokes) the control/button/etc.</p>
<h1>What IS provided by TVJS</h1>
<p>The TVJS library has a helper within it called <code>DirectionalNavigation</code> and is great in that it provides a focused and specific API to enable focus management while developing a Xbox App UWP Javascript (&amp; C#) apps.</p>
<p>Just dropping the library in is enough to get much of the basics to work with most web apps.</p>
<p>However, the conflict between this and WinJS comes into play because WinJS also tried to implement some of their own focus management and the mix of these two just doesn't quite cut it.</p>
<h1>Get rid of mouse cursor</h1>
<p>Well, this isn't really a hack:</p>
<p>If you're looking at building a UWP JavaScript app for the Xbox, and tried to run your app on the Xbox (in dev mode), you may have noticed that your app behaves almost like it was just another web-page and doesn't default the cursor focus the way other xbox apps work. You're app just has a mouse-like cursor.</p>
<p>The way to deal with this is just by accessing the browser's gamepad api. Now, the Microsoft TVJS TVHelpers DirectionalNavigation library automatically does this for you, but for a better experience if you don't want to wait for the browser to download this library, you can manually access the api to hide the mouse cursor by throwing this at the top of your start page EX: <code>index.html</code></p>
<pre><code>    <span class="hljs-tag">&lt;<span class="hljs-title">script</span>&gt;</span><span class="javascript">
        <span class="hljs-comment">// Hide the Xbox/Edge mouse cursor during load.</span>
        <span class="hljs-keyword">try</span> {
            navigator.getGamepads();
        } <span class="hljs-keyword">catch</span>(err) {
            <span class="hljs-built_in">console</span> &amp;&amp; <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error with navigator.getGamepads()'</span>, err);
        }
    </span><span class="hljs-tag">&lt;/<span class="hljs-title">script</span>&gt;</span>
</code></pre>
<p>Just by calling <code>navigator.getGamepads()</code>, this tells the browser/hosted web app that you are going to take control of the app's focus management and to hide the mouse cursor.</p>
<p>Once you've done this and your app loads up with the TVJS DirectionalNavigation library and in my case some WinJS controls, focus management mostly works (sort-of).</p>
<h1>Completely Remove XYFocus built-in to WinJS:</h1>
<p>This is about as ugly as they get...</p>
<p>The below code is bascially looking for the XYFocus handlers that WinJS is trying add to the document and we wan to not allow it to get added.</p>
<p>This XYFocus handler really creates havoc when we add the XYFocus handler from TVSJ DirectionalNavigation.</p>
<pre><code>// HacktyHackHack
// The goal of this is to remove XYFocus management from WinJS
<span class="hljs-list">(<span class="hljs-keyword">function</span><span class="hljs-list">()</span> {
  var totalRemovedHandlers = <span class="hljs-number">0</span><span class="hljs-comment">;</span>
  var checkRemovedHandler = function<span class="hljs-list">()</span> {
    totalRemovedHandlers++<span class="hljs-comment">;</span>
    if <span class="hljs-list">(<span class="hljs-keyword">totalRemovedHandlers</span> &gt; <span class="hljs-number">2</span>)</span> {
      console.error<span class="hljs-list">(<span class="hljs-string">"EEEK, removing more than 2 handlers... be sure to validate that we're removing the right ones..."</span>)</span><span class="hljs-comment">;</span>
    }
  }<span class="hljs-comment">;</span>
  var realAddEventListener = document.addEventListener<span class="hljs-comment">;</span>
  document.addEventListener = function<span class="hljs-list">(<span class="hljs-keyword">eventName</span>, handler, c)</span>{
    if <span class="hljs-list">(<span class="hljs-keyword">handler</span>.toString<span class="hljs-list">()</span>.indexOf<span class="hljs-list">(<span class="hljs-quoted">'function</span> _handleKeyEvent<span class="hljs-list">(<span class="hljs-keyword">e</span>)</span>')</span> &gt;= <span class="hljs-number">0</span>)</span> {
      console.warn<span class="hljs-list">(<span class="hljs-string">"Ignoring _handleKeyEvent..."</span>, eventName, handler, c)</span><span class="hljs-comment">;</span>
      checkRemovedHandler<span class="hljs-list">()</span><span class="hljs-comment">;</span>
      return<span class="hljs-comment">;</span>
    }
    if <span class="hljs-list">(<span class="hljs-keyword">handler</span>.toString<span class="hljs-list">()</span>.indexOf<span class="hljs-list">(<span class="hljs-quoted">'function</span> _handleCaptureKeyEvent<span class="hljs-list">(<span class="hljs-keyword">e</span>)</span>')</span> &gt;= <span class="hljs-number">0</span>)</span> {
      console.warn<span class="hljs-list">(<span class="hljs-string">"Ignoring _handleCaptureKeyEvent..."</span>, eventName, handler, c)</span><span class="hljs-comment">;</span>
      checkRemovedHandler<span class="hljs-list">()</span><span class="hljs-comment">;</span>
      return<span class="hljs-comment">;</span>
    }
    return realAddEventListener<span class="hljs-list">(<span class="hljs-keyword">eventName</span>, handler, c)</span><span class="hljs-comment">;</span>
  }<span class="hljs-comment">;</span>
}<span class="hljs-list">()</span>)</span><span class="hljs-comment">;</span>
</code></pre>
<p>By not allowing WinJS to add it's XYFocus handlers, we can avoid many of the issues that I worked through below...</p>
<h1>Dealing with a WinJS Pivot control</h1>
<p>For my app, the first control I ran into trouble with was the WinJS <a href="https://msdn.microsoft.com/en-us/library/windows/apps/dn624879.aspx">Pivot</a> control. This control already does some focus management all by itself, and it's own management style contradicts the way the DirectionalNavigation helper works. So we basically have to detect focus on it, turn of TVJS focus management and handle it internally (until we leave focus of the Pivot).</p>
<p>To work through that, I created the following helper function:</p>
<pre><code class="language-javascript">
WinJS.UI.Pivot.prototype._headersKeyDown = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.locked) {
        <span class="hljs-keyword">return</span>;
    }
    <span class="hljs-keyword">if</span> (e.keyCode === Keys.leftArrow ||
        e.keyCode === Keys.pageUp ||
        e.keyCode === Keys.GamepadDPadLeft ||
        e.keyCode === Keys.GamepadLeftThumbstickLeft) {
        <span class="hljs-keyword">this</span>._rtl ? <span class="hljs-keyword">this</span>._goNext() : <span class="hljs-keyword">this</span>._goPrevious();
        e.preventDefault();
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (e.keyCode === Keys.rightArrow ||
               e.keyCode === Keys.pageDown ||
               e.keyCode === Keys.GamepadDPadRight ||
               e.keyCode === Keys.GamepadLeftThumbstickRight) {
        <span class="hljs-keyword">this</span>._rtl ? <span class="hljs-keyword">this</span>._goPrevious() : <span class="hljs-keyword">this</span>._goNext();
        e.preventDefault();
    }
};

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handlePivotNavigation</span>(<span class="hljs-params">pivotElement</span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"handlePivotNavigation"</span>, pivotElement);
  <span class="hljs-keyword">if</span> (!pivotElement) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"handlePivotNavigation cannot use pivotElement as it wasn't passed in"</span>);
  }

  <span class="hljs-keyword">var</span> pivotHeader = pivotElement.querySelector(<span class="hljs-string">'.win-pivot-headers'</span>)

  <span class="hljs-keyword">if</span> (!pivotHeader) {
    <span class="hljs-keyword">let</span> msg = <span class="hljs-string">"handlePivotNavigation cannot find .win-pivot-headers in"</span>;
    <span class="hljs-built_in">console</span>.error(msg, pivotElement);
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(msg);
  }


  pivotHeader.addEventListener(<span class="hljs-string">'focus'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"pivotHeader focus"</span>);
    DirectionalNavigation.enabled = <span class="hljs-literal">false</span>;
  });
  pivotHeader.addEventListener(<span class="hljs-string">'keyup'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">eventInfo</span>) </span>{
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'pivot keyup '</span>, eventInfo.keyCode, eventInfo.key);

    <span class="hljs-keyword">switch</span>(eventInfo.keyCode) {
      <span class="hljs-keyword">case</span> <span class="hljs-number">204</span>: <span class="hljs-comment">// gampead down</span>
      <span class="hljs-keyword">case</span> <span class="hljs-number">40</span>: <span class="hljs-comment">// keyboard down</span>
        DirectionalNavigation.enabled = <span class="hljs-literal">true</span>;
        <span class="hljs-keyword">var</span> target = DirectionalNavigation.findNextFocusElement(<span class="hljs-string">'down'</span>);
        <span class="hljs-keyword">if</span> (target) {
          target.focus();
          eventInfo.preventDefault();
        }
        <span class="hljs-keyword">break</span>;
      <span class="hljs-keyword">case</span> <span class="hljs-number">203</span>: <span class="hljs-comment">// gamepad up</span>
        <span class="hljs-comment">// since the Pivot is at the top of the page - we won't release</span>
        <span class="hljs-comment">// control, or try to navigate up??? (maybe consider flowing up from the bottom of the page?)</span>
        <span class="hljs-keyword">break</span>;
      <span class="hljs-comment">// case 205: // gamepad left arrow</span>
      <span class="hljs-comment">// case 211: // gamepad 211 GamepadLeftThumbstickUp</span>
      <span class="hljs-comment">// case 200: // gamepad left bumper</span>
      <span class="hljs-comment">//   pivotElement.winControl._goPrevious();</span>
      <span class="hljs-comment">//   eventInfo.preventDefault();</span>
      <span class="hljs-comment">//   break;</span>
      <span class="hljs-comment">// case 206: // gamepad right arrow</span>
      <span class="hljs-comment">// case 213: // gamepad 213 GamepadLeftThumbstickRight</span>
      <span class="hljs-comment">// case 199: // gamepad 199 GamepadRightShoulder</span>
      <span class="hljs-comment">//   pivotElement.winControl._goNext();</span>
      <span class="hljs-comment">//   eventInfo.preventDefault();</span>
      <span class="hljs-comment">//   break;</span>
    }
  });
}
</code></pre>
<p>And use it by doing the following in my React page:</p>
<pre><code class="language-javascript">    componentDidMount() {
        <span class="hljs-keyword">var</span> pivot = ReactDOM.findDOMNode(<span class="hljs-keyword">this</span>.refs.pivot);
        handlePivotNavigation(pivot);
    }
</code></pre>
<p>Or if you're not using React you can likely just go:</p>
<pre><code class="language-javascript">    <span class="hljs-keyword">var</span> pivot = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'my-pivot-id'</span>);
    handlePivotNavigation(pivot);
</code></pre>
<blockquote>
<p>It's not pretty, but has been working for me so far.</p>
</blockquote>
<p>Now when I navigate around using an Xbox controller I can properly navigate around the WinJS Pivot.</p>
<h1>Next up are <code>ItemContainer</code>s.</h1>
<h3>UPDATE:</h3>
<blockquote>
<p>With the added (remove XYFocus above - I removed the below hack)</p>
</blockquote>
<p>This one is a total hack, and I look forward to a better solution, but for now it's been working.</p>
<p>The issue I was seeing was with WinJS <a href="https://msdn.microsoft.com/en-us/library/windows/apps/dn255188.aspx">ItemContainers</a> and the TVJS library applying a separate forced &quot;click&quot; on the element when the control itself has already &quot;clicked/invoked&quot; the element.</p>
<p>The real fix would likely to figure out how to get the ItemContainer to <code>event.preventDefault()</code> and/or <code>event.stopPropagation()</code> and avoid the bubbling up to the <code>document</code> <code>keyup</code> event handler that DirectionalNavigation has under it's control, but WinJS ItemControl management is just so complicated that this hack was easier to figure out at the time I threw it together.</p>
<p>So what does this do?</p>
<p>It's basically hijacking the DirectionalNavigation._handleKeyUpEvent function, and re-writing it with one that ignores the <code>keyup</code> event if the currently focused element is an ItemContainer.</p>
<pre><code class="language-javascript"><span class="hljs-comment">// Hack to avoid Item containers getting double click</span>
<span class="hljs-keyword">var</span> originalDNKeyUp = TVJS.DirectionalNavigation._handleKeyUpEvent
TVJS.DirectionalNavigation._handleKeyUpEvent = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Check for itemContaner"</span>, event.target.className)
  <span class="hljs-keyword">if</span> (e.target.className.split(<span class="hljs-string">" "</span>).indexOf(<span class="hljs-string">"win-itemcontainer"</span>) &gt;= <span class="hljs-number">0</span>) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"MonkeyHack on DirectionalNavigation - SKIPPING CLICK"</span>);
    <span class="hljs-keyword">return</span>;
  }
  <span class="hljs-keyword">return</span> originalDNKeyUp.apply(<span class="hljs-literal">null</span>, <span class="hljs-built_in">arguments</span>);
}
<span class="hljs-built_in">document</span>.removeEventListener(<span class="hljs-string">"keyup"</span>, originalDNKeyUp);
<span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">"keyup"</span>, TVJS.DirectionalNavigation._handleKeyUpEvent);
</code></pre>
<p>It's not pretty, but meh, is working so far.</p>
<h1>ItemContainers within a ContentDialog</h1>
<h3>UPDATE</h3>
<blockquote>
<p>I gave up on ContentDialog, and just started using <a href="https://github.com/reactjs/react-modal">react-modal</a></p>
</blockquote>
<p>That's just a big mess from what I could figure out. I was able to get it working by using the <code>ContentDialog</code> but manually creat my own buttons as the <code>ItemContainer</code> in combination with the dialog kept swallowing events that didn't allow focus navigation to be sucessful. The internals of what was holding me back didn't appear to be monkey-patch-able from what I could tell... ugh...</p>
<h1>Next up is a <code>ListView</code> hack,</h1>
<p>This one is a hack proposed by Todd over on the <a href="https://github.com/winjs/winjs/issues/1546">GitHub issues</a>.</p>
<p>I've essentially taken the original implementation of WinJS.UI.ListView.prototype._onFocusIn, and if you look for the line starting with <code>/* JJ */</code> below you can see the change there.</p>
<p>Don't know what this actually could mean from other scenarios, but for now it's allowing the ListView to focus properly on my initial xbox testing.</p>
<pre><code><span class="hljs-keyword">var</span> _Constants = <span class="hljs-type">WinJS</span>.<span class="hljs-type">UI</span>;
<span class="hljs-keyword">var</span> _UI = <span class="hljs-type">WinJS</span>.<span class="hljs-type">UI</span>;

<span class="hljs-type">WinJS</span>.<span class="hljs-type">UI</span>.<span class="hljs-type">ListView</span>.prototype._onFocusIn = function <span class="hljs-type">ListView_onFocusIn</span>(event) {
                    <span class="hljs-keyword">this</span>._hasKeyboardFocus = <span class="hljs-literal">true</span>;
                    <span class="hljs-keyword">var</span> that = <span class="hljs-keyword">this</span>;
                    function moveFocusToItem(keyboardFocused) {
                        that._changeFocus(that._selection._getFocused(), <span class="hljs-literal">true</span>, <span class="hljs-literal">false</span>, <span class="hljs-literal">false</span>, keyboardFocused);
                    }
                    <span class="hljs-comment">// The keyboardEventsHelper object can get focus through three ways: We give it focus explicitly, in which case _shouldHaveFocus will be true,</span>
                    <span class="hljs-comment">// or the item that should be focused isn't in the viewport, so keyboard focus could only go to our helper. The third way happens when</span>
                    <span class="hljs-comment">// focus was already on the keyboard helper and someone alt tabbed away from and eventually back to the app. In the second case, we want to navigate</span>
                    <span class="hljs-comment">// back to the focused item via changeFocus(). In the third case, we don't want to move focus to a real item. We differentiate between cases two and three</span>
                    <span class="hljs-comment">// by checking if the flag _keyboardFocusInbound is true. It'll be set to true when the tab manager notifies us about the user pressing tab</span>
                    <span class="hljs-comment">// to move focus into the listview.</span>
                    <span class="hljs-keyword">if</span> (event.target === <span class="hljs-keyword">this</span>._keyboardEventsHelper) {
                        <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>._keyboardEventsHelper._shouldHaveFocus &amp;&amp; <span class="hljs-keyword">this</span>._keyboardFocusInbound) {
                            moveFocusToItem(<span class="hljs-literal">true</span>);
                        } <span class="hljs-keyword">else</span> {
                            <span class="hljs-keyword">this</span>._keyboardEventsHelper._shouldHaveFocus = <span class="hljs-literal">false</span>;
                        }
                    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (event.target === <span class="hljs-keyword">this</span>._element) {
                        <span class="hljs-comment">// If someone explicitly calls .focus() on the listview element, we need to route focus to the item that should be focused</span>
                        moveFocusToItem();
                    } <span class="hljs-keyword">else</span> {
                        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._mode.inboundFocusHandled) {
                            <span class="hljs-keyword">this</span>._mode.inboundFocusHandled = <span class="hljs-literal">false</span>;
                            <span class="hljs-keyword">return</span>;
                        }

                        <span class="hljs-comment">// In the event that .focus() is explicitly called on an element, we need to figure out what item got focus and set our state appropriately.</span>
                        <span class="hljs-keyword">var</span> items = <span class="hljs-keyword">this</span>._view.items,
                            entity = {},
                            element = <span class="hljs-keyword">this</span>._getHeaderOrFooterFromElement(event.target),
                            winItem = <span class="hljs-literal">null</span>;
                        <span class="hljs-keyword">if</span> (element) {
                            entity.index = <span class="hljs-number">0</span>;
                            entity.<span class="hljs-keyword">type</span> = (element === <span class="hljs-keyword">this</span>._header ? _UI.<span class="hljs-type">ObjectType</span>.header : _UI.<span class="hljs-type">ObjectType</span>.footer);
                            <span class="hljs-keyword">this</span>._lastFocusedElementInGroupTrack = entity;
                        } <span class="hljs-keyword">else</span> {
                            element = <span class="hljs-keyword">this</span>._groups.headerFrom(event.target);
                            <span class="hljs-keyword">if</span> (element) {
                                entity.<span class="hljs-keyword">type</span> = _UI.<span class="hljs-type">ObjectType</span>.groupHeader;
                                entity.index = <span class="hljs-keyword">this</span>._groups.index(element);
                                <span class="hljs-keyword">this</span>._lastFocusedElementInGroupTrack = entity;
                            } <span class="hljs-keyword">else</span> {
                                entity.index = items.index(event.target);
                                entity.<span class="hljs-keyword">type</span> = _UI.<span class="hljs-type">ObjectType</span>.item;
                                element = items.itemBoxAt(entity.index);
                                winItem = items.itemAt(entity.index);
                            }
                        }

                        <span class="hljs-comment">// In the old layouts, index will be -1 if a group header got focus</span>
                        <span class="hljs-keyword">if</span> (entity.index !== _Constants._INVALID_INDEX) {
<span class="hljs-comment">/* JJ */</span>                            <span class="hljs-comment">/*if (this._keyboardFocusInbound || this._selection._keyboardFocused())*/</span> {
                                <span class="hljs-keyword">if</span> ((entity.<span class="hljs-keyword">type</span> === _UI.<span class="hljs-type">ObjectType</span>.groupHeader &amp;&amp; event.target === element) ||
                                        (entity.<span class="hljs-keyword">type</span> === _UI.<span class="hljs-type">ObjectType</span>.item &amp;&amp; event.target.parentNode === element)) {
                                    <span class="hljs-comment">// For items we check the parentNode because the srcElement is win-item and element is win-itembox,</span>
                                    <span class="hljs-comment">// for header, they should both be the win-groupheader</span>
                                    <span class="hljs-keyword">this</span>._drawFocusRectangle(element);
                                }
                            }
                            <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>._tabManager.childFocus !== element &amp;&amp; <span class="hljs-keyword">this</span>._tabManager.childFocus !== winItem) {
                                <span class="hljs-keyword">this</span>._selection._setFocused(entity, <span class="hljs-keyword">this</span>._keyboardFocusInbound || <span class="hljs-keyword">this</span>._selection._keyboardFocused());
                                <span class="hljs-keyword">this</span>._keyboardFocusInbound = <span class="hljs-literal">false</span>;
                                <span class="hljs-keyword">if</span> (entity.<span class="hljs-keyword">type</span> === _UI.<span class="hljs-type">ObjectType</span>.item) {
                                    element = items.itemAt(entity.index);
                                }
                                <span class="hljs-keyword">this</span>._tabManager.childFocus = element;

                                <span class="hljs-keyword">if</span> (that._updater) {
                                    <span class="hljs-keyword">var</span> elementInfo = that._updater.elements[uniqueID(element)],
                                        focusIndex = entity.index;
                                    <span class="hljs-keyword">if</span> (elementInfo &amp;&amp; elementInfo.newIndex) {
                                        focusIndex = elementInfo.newIndex;
                                    }

                                    <span class="hljs-comment">// Note to not set old and new focus to the same object</span>
                                    that._updater.oldFocus = { <span class="hljs-class"><span class="hljs-keyword">type</span>:</span> entity.<span class="hljs-keyword">type</span>, index: focusIndex };
                                    that._updater.newFocus = { <span class="hljs-class"><span class="hljs-keyword">type</span>:</span> entity.<span class="hljs-keyword">type</span>, index: focusIndex };
                                }
                            }
                        }
                    }
                }
</code></pre>
<p>One big improvement could be to consider setting up a unit-test that could take the original &quot;string&quot; value of the entire function code, and comparing it to the current version of WinJS library you're using and fail if they're even one character different. This would allow you to detect if say a fix were applied, or you need to update our local hacked version with some remote changes... It's not pretty, but one way to avoid over-writing possible working WinJS code with our potentially not-so-future-proof hacked version.</p>
<h1>Next one is the WinJS [ToggleSwitch].</h1>
<p>This control just seemed to have all behavior wrong for me. So I hacked the keyDownHandler and simplified it's implementation which seems to have really made it more usable (for me).</p>
<pre><code><span class="hljs-keyword">var</span> _ElementUtilities = WinJS.Utilities

WinJS.UI.ToggleSwitch.prototype._keyDownHandler =  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ToggleSwitch_keyDown</span><span class="hljs-params">(e)</span> </span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.disabled) {
        <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-comment">// Toggle checked on spacebar</span>
    <span class="hljs-keyword">if</span> (e.keyCode === _ElementUtilities.Key.space ||
        e.keyCode === _ElementUtilities.Key.GamepadA ||
        e.keyCode === _ElementUtilities.Key.enter) {
        e.preventDefault();
        <span class="hljs-keyword">this</span>.checked = !<span class="hljs-keyword">this</span>.checked;
    }

}
</code></pre>
<p>The original had up/down/left/right configured to toggle the switch on/off which meant focus in/out was nearly impossible, it also only listened to <code>space</code> as a toggle option. So by removing the up/down/left/right we can navigate in/around the control and we wanted to listen to <code>space, GamepadA, and enter</code> to toggle the control on/off.</p>
<h1>What else?</h1>
<p>The WinJS control set is quite large, and I certainly haven't worked with each control in this manor, however, it's a step forward eh and if you managed to come across this random post on the interweb I hope it was useful?</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Slightly modified “CD” Command for Powershell: Even better dot.dot.dot.dot...]]></title>
        <id>https://staxmanade.com/2016/11/slightly-modified-cd-command-for-powershell-even-better-dot-dot-dot/</id>
        <link href="https://staxmanade.com/2016/11/slightly-modified-cd-command-for-powershell-even-better-dot-dot-dot/">
        </link>
        <updated>2016-11-15T05:06:36.036Z</updated>
        <summary type="html"><![CDATA[There's this little "CD" utility that I iterate on every once in while but has become one of my favorite PowerShell tools on Windows.]]></summary>
        <content type="html"><![CDATA[<p>There's this little &quot;CD&quot; utility that I iterate on every once in while but has become one of my favorite PowerShell tools on Windows.</p>
<p>Not because it's really that great, but more because there are some navigation habits I acquire over on a Mac in a ZSH terminal that become challenging to not have on a Windows PowerShell terminal and each time I iterate on it, it synchronizes my workflows on both Mac and Windows environments.</p>
<p>In my <a href="https://staxmanade.com/2016/04/slightly-modified--cd--command-for-powershell--now-with-dot-dot-dot-dot---/">previous update</a> I added support for typing <code>cd ...N</code> where <code>cd ..</code> will go up 1 directory, so <code>cd ....</code> will go up 3 directories.</p>
<p>Well today I found out that I can declare a function in powershell with a name <code>..</code> - WHO KNEW?</p>
<p>For example if you pasted the following into your PowerShell terminal: <code>function ..() { echo &quot;HELLO&quot;; }; ..</code></p>
<p>This would define the function <code>..</code> as well as run it and print out <code>HELLO</code>.</p>
<p>This was a fantastic stumbling on my part because on my Mac I often go up 1-n directories by typing <code>..</code> at the terminal or <code>.....</code> &lt;-- however many I want to go up.</p>
<p>So today I updated the <a href="https://github.com/staxmanade/DevMachineSetup/blob/master/GlobalScripts/Change-Directory.ps1">Change-Directory.ps1</a> with the following shortcuts:</p>
<pre><code class="language-powershell"><span class="hljs-keyword">function</span> ..() { cd .. }
<span class="hljs-keyword">function</span> ...() { cd ... }
<span class="hljs-keyword">function</span> ....() { cd .... }
<span class="hljs-keyword">function</span> .....() { cd ..... }
<span class="hljs-keyword">function</span> ......() { cd ...... }
<span class="hljs-keyword">function</span> .......() { cd ....... }
<span class="hljs-keyword">function</span> ........() { cd ........ }
</code></pre>
<p>If you're interested in the evolution of this CD tool:</p>
<ul>
<li><a href="https://staxmanade.com/2011/07/slightly-modified-cd-command-for/">Slightly modified “CD” Command for Powershell</a></li>
<li><a href="https://staxmanade.com/2012/11/more-than-slightly-modified-cd-command/">More than slightly modified “CD” command for PowerShell</a></li>
<li><a href="https://staxmanade.com/2016/04/slightly-modified--cd--command-for-powershell--now-with-dot-dot-dot-dot---/">Slightly modified “CD” Command for Powershell: Now with dot.dot.dot.dot...</a></li>
</ul>
<p>SUPER SWEET!</p>
<p>Happy CD'ing!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Better Compact JIRA Board U.I.]]></title>
        <id>https://staxmanade.com/2016/09/better-compact-jira-board-u-i-/</id>
        <link href="https://staxmanade.com/2016/09/better-compact-jira-board-u-i-/">
        </link>
        <updated>2016-09-30T17:07:25.328Z</updated>
        <summary type="html"><![CDATA[We use JIRA's kanban board for daily workflow of tasks. I started having an issue with the default JIRA board layout where the cards do not show enoug...]]></summary>
        <content type="html"><![CDATA[<p>We use JIRA's kanban board for daily workflow of tasks. I started having an issue with the default JIRA board layout where the cards do not show enough of a task's title, especially when you pseudo-group tickets by prefixing their title with some context.</p>
<p>Given that, I decided to hack the CSS of JIRA's board to improve this. Take a look at an example before/after of the tweaks below, then I'll walk through how you can get it if you so desire.</p>
<h1>Before</h1>
<p><img src="/images/posts/JIRA-Card-BEFORE.png" alt="Jira card before css hack"></p>
<h1>After CSS Hack</h1>
<p><img src="/images/posts/JIRA-Card-AFTER.png" alt="Jira card before css hack"></p>
<h1>How did you do that?</h1>
<ol>
<li>Install a CSS style plugin into your browser. This post all use <a href="https://chrome.google.com/webstore/detail/stylebot/oiaejidbmkiecgbjeifoejpgmdaleoha?hl=en">Stylebot</a> for the Chrome web browser.</li>
</ol>
<ul>
<li>Just install the plugin from the Chrome store by <a href="https://chrome.google.com/webstore/detail/stylebot/oiaejidbmkiecgbjeifoejpgmdaleoha?hl=en">clicking this link</a> and selecting <code>[+ ADD TO CHROME]</code> button on the upper right of the page.</li>
</ul>
<ol start="2">
<li>
<p>Once the plugin is installed. Close all tabs and re-open a tab to the JIRA kanban board.</p>
</li>
<li>
<p>Click the new Stylebot plugin <code>CSS</code> button and the <code>Open Stylebot...</code> option in your chrome browser toolbar which will open up a U.I. that allow you to mess around with the page's style.</p>
</li>
<li>
<p>At the bottom of the Stylebot click <code>Edit CSS</code> which will give you a blank text box you can write custom CSS into.</p>
</li>
<li>
<p>Paste in the following CSS and hit <code>Save</code></p>
</li>
</ol>
<pre><code class="language-css">
<span class="hljs-comment">/** Version 2.3
 ** Copyright Jason Jarrett
 **/</span>

<span class="hljs-class">.ghx-avatar-img</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">font-size</span>:<span class="hljs-value"> <span class="hljs-number">15px</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">height</span>:<span class="hljs-value"> <span class="hljs-number">15px</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">line-height</span>:<span class="hljs-value"> <span class="hljs-number">15px</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">width</span>:<span class="hljs-value"> <span class="hljs-number">15px</span></span></span>;
}</span>

<span class="hljs-class">.ghx-band-1</span> <span class="hljs-class">.ghx-issue</span> <span class="hljs-class">.ghx-avatar</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">left</span>:<span class="hljs-value"> <span class="hljs-number">100px</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">right</span>:<span class="hljs-value"> auto</span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">top</span>:<span class="hljs-value"> -<span class="hljs-number">3px</span></span></span>;
}</span>

<span class="hljs-class">.ghx-band-3</span> <span class="hljs-class">.ghx-issue</span> <span class="hljs-class">.ghx-avatar</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">top</span>:<span class="hljs-value"> <span class="hljs-number">0px</span></span></span>;
}</span>

<span class="hljs-class">.ghx-issue</span> <span class="hljs-class">.ghx-extra-fields</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">margin-top</span>:<span class="hljs-value"> <span class="hljs-number">5px</span></span></span>;
}</span>

<span class="hljs-class">.ghx-issue</span> <span class="hljs-class">.ghx-flags</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">left</span>:<span class="hljs-value"> <span class="hljs-number">20px</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">top</span>:<span class="hljs-value"> <span class="hljs-number">5px</span></span></span>;
}</span>

<span class="hljs-class">.ghx-issue</span> <span class="hljs-class">.ghx-highlighted-fields</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">margin-top</span>:<span class="hljs-value"> <span class="hljs-number">5px</span></span></span>;
}</span>

<span class="hljs-class">.ghx-issue</span> <span class="hljs-class">.ghx-type</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">left</span>:<span class="hljs-value"> <span class="hljs-number">5px</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">top</span>:<span class="hljs-value"> <span class="hljs-number">5px</span></span></span>;
}</span>

<span class="hljs-class">.ghx-issue-content</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">font-size</span>:<span class="hljs-value"> <span class="hljs-number">12px</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">margin-top</span>:<span class="hljs-value"> <span class="hljs-number">3px</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">padding</span>:<span class="hljs-value"> <span class="hljs-number">5px</span></span></span>;
}</span>

<span class="hljs-class">.ghx-issue-fields</span> <span class="hljs-class">.ghx-key</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">margin-left</span>:<span class="hljs-value"> <span class="hljs-number">30px</span></span></span>;
}</span>

<span class="hljs-class">.ghx-issue</span><span class="hljs-class">.ghx-has-avatar</span> <span class="hljs-class">.ghx-issue-fields</span>, <span class="hljs-class">.ghx-issue</span><span class="hljs-class">.ghx-has-corner</span> <span class="hljs-class">.ghx-issue-fields</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">padding-right</span>:<span class="hljs-value"> <span class="hljs-number">0px</span></span></span>;
}</span>

<span class="hljs-comment">/* the below adjusts the backlog view */</span>

<span class="hljs-class">.ghx-backlog-column</span> <span class="hljs-class">.ghx-plan-extra-fields</span><span class="hljs-class">.ghx-row</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">float</span>:<span class="hljs-value"> right</span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">position</span>:<span class="hljs-value"> relative</span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">right</span>:<span class="hljs-value"> <span class="hljs-number">70px</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">margin</span>:<span class="hljs-value"> <span class="hljs-number">0</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">margin-top</span>:<span class="hljs-value"> -<span class="hljs-number">15px</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">height</span>:<span class="hljs-value"> <span class="hljs-number">18px</span></span></span>;
}</span>

<span class="hljs-class">.ghx-backlog-column</span> <span class="hljs-class">.ghx-issue-content</span>, <span class="hljs-class">.ghx-backlog-column</span> <span class="hljs-class">.ghx-end</span><span class="hljs-class">.ghx-row</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">padding</span>:<span class="hljs-value"> <span class="hljs-number">0</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">margin</span>:<span class="hljs-value"> <span class="hljs-number">0</span></span></span>;
}</span>

<span class="hljs-comment">/* filters */</span>
<span class="hljs-class">.js-quickfilter-button</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">padding</span>:<span class="hljs-value"> <span class="hljs-number">0</span></span></span>;
}</span>
<span class="hljs-class">.js-sprintfilter</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">white-space</span>:<span class="hljs-value"> nowrap</span></span>;
}</span>
<span class="hljs-class">.js-sprintfilter</span> &gt; <span class="hljs-tag">span</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">padding</span>:<span class="hljs-value"> <span class="hljs-number">0</span></span></span>;
}</span>
<span class="hljs-tag">dl</span> <span class="hljs-tag">dt</span>, <span class="hljs-tag">dd</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">margin</span>:<span class="hljs-value"> <span class="hljs-number">0</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">padding</span>:<span class="hljs-value"> <span class="hljs-number">0</span></span></span>;
}</span>

<span class="hljs-tag">span</span><span class="hljs-class">.ghx-extra-field</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">margin-right</span>:<span class="hljs-value"> <span class="hljs-number">100px</span></span></span>;
}</span>

<span class="hljs-tag">span</span><span class="hljs-class">.ghx-end</span><span class="hljs-class">.ghx-extra-field-estimate</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">padding-top</span>:<span class="hljs-value"> <span class="hljs-number">0</span></span></span>;
    <span class="hljs-rule"><span class="hljs-attribute">padding-bottom</span>:<span class="hljs-value"> <span class="hljs-number">0</span></span></span>;
}</span>

<span class="hljs-tag">div</span><span class="hljs-class">.ghx-plan-extra-fields</span><span class="hljs-class">.ghx-plan-extra-fields-1</span><span class="hljs-class">.ghx-row</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">height</span>:<span class="hljs-value"> <span class="hljs-number">20px</span></span></span>;
}</span>

<span class="hljs-class">.ghx-issue-compact</span> <span class="hljs-class">.ghx-row</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">margin</span>:<span class="hljs-value"> <span class="hljs-number">0px</span></span></span>;
}</span>
<span class="hljs-tag">div</span><span class="hljs-class">.ghx-plan-extra-fields</span><span class="hljs-class">.ghx-plan-extra-fields-1</span><span class="hljs-class">.ghx-row</span> <span class="hljs-rules">{
    <span class="hljs-rule"><span class="hljs-attribute">margin-top</span>:<span class="hljs-value"> <span class="hljs-number">0</span></span></span>;
}</span>
</code></pre>
<p>Now you should get a little bit more visible data on the page and be able to avoid hovering over titles to get enough context of the ticket to immediately know what it is.</p>
<p>Happy (as best you can) JIRA'ing</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[How to Update a Single Running docker-compose Container]]></title>
        <id>https://staxmanade.com/2016/09/how-to-update-a-single-running-docker-compose-container/</id>
        <link href="https://staxmanade.com/2016/09/how-to-update-a-single-running-docker-compose-container/">
        </link>
        <updated>2016-09-09T04:45:17.565Z</updated>
        <summary type="html"><![CDATA[As a newbie to the tooling, [docker-compose](https://docs.docker.com/compose/) it's great for getting started. To bring up all the service containers ...]]></summary>
        <content type="html"><![CDATA[<p>As a newbie to the tooling, <a href="https://docs.docker.com/compose/">docker-compose</a> it's great for getting started. To bring up all the service containers with a simple <code>docker-compose up</code> starts everything. However, what if you want to replace an existing container without tearing down the entire suite of containers?</p>
<p>For example: I have a <code>docker-compose</code> project that has the following containers.</p>
<ol>
<li>Node JS App</li>
<li>CouchDB</li>
<li>Redis Cache</li>
</ol>
<p>I had a small configuration change within the CouchDB container that I wanted to update and re-start to get going but wasn't sure how to do that.</p>
<h1>Here's how I did it with little down time.</h1>
<p>I'm hoping there are better ways to go about this (I'm still learning), but the following steps are what I used to replace a running docker container with the latest build.</p>
<ol>
<li>Make the necessary change to the container (in my case update the couchdb config).</li>
<li>Run <code>docker-compose build couchdb</code> (<code>docker-compose build &lt;service_name&gt;</code> where <code>service_name</code> is the name of the docker container defined in your <code>docker-compose.yml</code> file.)</li>
</ol>
<p>Once the change has been made and container re-built, we need to get that new container running (without affecting the other containers that were started by docker-compose).</p>
<ol>
<li><code>docker-compose stop &lt;service_name&gt;</code> &lt;-- If you want to live on the edge and have the shut-down go faster, try <code>docker-compose kill &lt;service_name&gt;</code></li>
<li><code>docker-compose up -d --no-deps &lt;service_name&gt;</code> &lt;-- this brings up the service using the newly built container.</li>
</ol>
<p>The <code>-d</code> is Detached mode: Run containers in the background, print new container names.</p>
<p>The <code>--no-deps</code> will not start linked services.</p>
<p>That's it... at least for me, it's worked to update my running containers with the latest version without tearing down the entire docker-compose set of services.</p>
<blockquote>
<p>Again, if you know of a faster/better way to go about this, I'd love to hear it. Or if you know of any down-sides to this approach, I'd love to hear about it before I have to learn the hard way on a production environment.</p>
</blockquote>
<h2>UPDATE:</h2>
<p>Thanks to Vladimir in the comments below - you can skip several steps above and do it with a single command</p>
<pre><code><span class="hljs-comment">docker</span><span class="hljs-literal">-</span><span class="hljs-comment">compose</span> <span class="hljs-comment">up</span> <span class="hljs-literal">-</span><span class="hljs-comment">d</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">no</span><span class="hljs-literal">-</span><span class="hljs-comment">deps</span> <span class="hljs-literal">-</span><span class="hljs-literal">-</span><span class="hljs-comment">build</span> &lt;<span class="hljs-comment">service_name</span>&gt;
</code></pre>
<p>I tested this and was able to avoid the <code>build</code>, <code>kill</code>, and <code>up</code> commands with this one-liner.</p>
<p>Happy Container Updating!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Run Multiple Docker Environments (qa, stage, prod) from the Same docker-compose File.]]></title>
        <id>https://staxmanade.com/2016/07/run-multiple-docker-environments--qa--beta--prod--from-the-same-docker-compose-file-/</id>
        <link href="https://staxmanade.com/2016/07/run-multiple-docker-environments--qa--beta--prod--from-the-same-docker-compose-file-/">
        </link>
        <updated>2016-07-27T05:24:03.338Z</updated>
        <summary type="html"><![CDATA[So, I'm playing around with some personal projects and looking to deploy some simple things with [Docker](https://www.docker.com/) to DigitalOcean. Th...]]></summary>
        <content type="html"><![CDATA[<p>So, I'm playing around with some personal projects and looking to deploy some simple things with <a href="https://www.docker.com/">Docker</a> to DigitalOcean. This personal project is a small site, and I'd like to set myself up with a repeatable deployment solution (that may be automated as much as possible) so I don't trip over myself with server hosting as I build out the web application.</p>
<p>I'm not really strong with server infrastructure and some of this is &quot;figure it out as I go&quot;, while more of it is asking for help from a good friend <a href="https://twitter.com/icecreammatt">@icecreammatt</a> who has been a HUGE help as I stumble through this.</p>
<p>But at the end of this tutorial our goal is to satisfy the following requirements.</p>
<h1>High level requirements:</h1>
<p>Below are some core requirements this walk-through should help address. There is likely room for improvement, and I'd love to hear any feedback you have along the way to simplify things or make them more secure. But hopefully you find this useful.</p>
<p>I want there to be some semblance of a release process with various deployment environments. Push changes to <code>qa</code> regularly, push semi-frequently to <code>stage</code> and when things are good, ship a version to production.</p>
<ol>
<li>Have access to environments through various domain names. EX: if prod was <code>my-docker-test-site.com</code> then I would also have <code>qa.my-docker-test-site.com</code> and <code>stage.my-docker-test-site.com</code></li>
<li>Ability to run multiple &quot;environments&quot;: <code>qa</code>, <code>stage</code>, <code>prod</code> in the same system. (prob not that many environments - but you get the picture)</li>
<li>Deploy to various environments without affecting other environments. (Ship updates to qa)</li>
<li>It'd be great if I can figure out a mostly zero-downtime deployment. (Not looking for perfect, but the less downtime the better)</li>
<li>Keep costs low. For a small site - running all environments on say a small DigitalOcean droplet. (Is this even possible? We'll see...)</li>
<li>Build various environments, test them out locally and then deploy them to the cloud (<img class="emoji" title="cloud" alt="cloud" src="https://assets-cdn.github.com/images/icons/emoji/unicode/2601.png" height="20" width="20" align="absmiddle">)</li>
</ol>
<p>While I'd like the ability to run as many environments as I listed above, I will likely use a <code>qa</code> and <code>prod</code> for my small site, but I think the pattern is such that we could easily setup whatever environments we need.</p>
<h1>Structure of post:</h1>
<p>What we want to do is essentially walk through how I'm thinking about accomplishing the above high level requirements using a simple <a href="https://nodejs.org/en/">node js</a> hello world application. This app is a basic node app that renders some environment information just to prove that we can correctly configure and deploy various docker containers for environments such as <code>qa</code>, <code>stage</code> or <code>prod</code>.</p>
<p>In the end, we should end up with something that I like to imagine looks a bit like this diagram:</p>
<img alt="diagram of nginx-proxy in front of web app containers on a DigitalOcean droplet" src="/images/posts/VisualOfContainers.svg" style="border:0; box-shadow: none" />
<p>I'm going to use <a href="https://m.do.co/c/451940554550">DigitalOcean</a> as the cloud provider in this case, but I think this pattern could be to other docker hosting environments.</p>
<h1>Example Web App Structure</h1>
<p>Below is a basic view of the file structure of our site. If you're following along, go ahead and create this structure with empty files, we can fill them in as we go...</p>
<pre><code>.
|<span class="hljs-string">____app
</span>|<span class="hljs-string"> </span>|____Dockerfile
|<span class="hljs-string"> </span>|<span class="hljs-string">____server.js
</span>|<span class="hljs-string">____docker-compose.yml
</span></code></pre>
<p>Let's start with the <code>./app/*</code> files:</p>
<h2>Simple NodeJS Hello World app</h2>
<p>This is a simple nodejs server that we can use to show that deployment environment variables are passed through and we are running the correct <code>environment</code>. As well as showing a functioning web server.</p>
<p>File: <code>./app/server.js</code></p>
<pre><code><span class="hljs-keyword">var</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http'</span>);

<span class="hljs-keyword">var</span> server = http.createServer(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>)</span>{
    res.writeHead(<span class="hljs-number">200</span>, {<span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"text/plain"</span>});
    res.end(<span class="hljs-string">`
Hello World!

VIRTUAL_HOST: <span class="hljs-subst">${process.env.VIRTUAL_HOST}</span>
NODE_ENV: <span class="hljs-subst">${process.env.NODE_ENV}</span>
PORT: <span class="hljs-subst">${process.env.PORT}</span>

`</span>.split(<span class="hljs-string">'/n'</span>).join(<span class="hljs-string">'&lt;br&gt;'</span>));
});

server.listen(<span class="hljs-number">80</span>);
</code></pre>
<p>The goal of this file is to run a nodejs web server that will return a text document with <code>Hello World!</code> along with the environment variables that the current container are running under such as <code>qa</code>.</p>
<p>This could easily be replaced with a python, php or ruby, or a whatever web server. Just keep in mind the rest of the article may assume it's a node environment (like the <code>Dockerfile</code> up next). So adjust accordingly.</p>
<h2>The Dockerfile</h2>
<p>Below is pretty basic and says, load up and run our nodejs <code>server.js</code> web app on port <code>80</code>.</p>
<p>File: <code>./app/Dockerfile</code></p>
<pre><code><span class="hljs-comment"># Start from a standard nodejs image</span>
<span class="hljs-built_in">FROM</span> node

<span class="hljs-comment"># Copy in the node app to the container</span>
<span class="hljs-built_in">COPY</span> <span class="bash">./server.js /app/server.js
</span><span class="hljs-built_in">WORKDIR</span> <span class="bash">/app
</span>
<span class="hljs-comment"># Allow http connections to the server</span>
<span class="hljs-built_in">EXPOSE</span> <span class="hljs-number">80</span>

<span class="hljs-comment"># Start the node server</span>
<span class="hljs-built_in">CMD</span> <span class="bash">[<span class="hljs-string">"node"</span>, <span class="hljs-string">"server.js"</span>]
</span></code></pre>
<h1>How to get the qa, prod domain mappings</h1>
<p>So now that we have a basic application defined, we <strong>can't</strong> host multiple versions of the app all using port <code>80</code> without issue. One approach we can take would be to place an Nginx proxy in front of our containers to allow translation of incoming domain name requests to our various web app containers which we'll use docker to host on different ports.</p>
<p>The power here is we don't have to change the port within the docker container (as shown in the <code>Dockerfile</code> above) but we can use the port mapping feature when starting up the docker container to specify different ports for different environments.</p>
<p>For example I'd like <code>my-docker-test-site.com</code> to map to the production container, <code>qa.my-docker-test-site.com</code> the <code>qa</code> container of my site, etc... I'd rather not access <code>my-docker-test-site.com:7893</code> or some port for <code>qa</code>, <code>stage</code>, etc...</p>
<p>To accomplish this we are going to use <a href="https://github.com/jwilder/nginx-proxy">jwilder/nginx-proxy</a>. Check out his <a href="http://jasonwilder.com/blog/2014/03/25/automated-nginx-reverse-proxy-for-docker/">introductory blog post</a> on the project. We'll be using the <a href="https://hub.docker.com/r/jwilder/nginx-proxy/">pre-build container</a> directly.</p>
<p>To spin this up on our local system let's issue the following command:</p>
<pre><code>docker run -d -<span class="hljs-tag">p</span> <span class="hljs-number">80</span>:<span class="hljs-number">80</span> --name nginx-proxy -v /var/run/docker<span class="hljs-class">.sock</span>:/tmp/docker<span class="hljs-class">.sock</span>:ro jwilder/nginx-proxy
</code></pre>
<p>This project is great, now, as we add new or remove containers they will automatically be added/removed to the proxy and we should be able to access their web servers through a <code>VIRTUAL_HOST</code>. (more on how specifically below)</p>
<h1>Networking</h1>
<p>Before we get too far into the container environment of our app, we need to consider how the containers will be talking to each other.</p>
<p>We can do this using the <code>docker network</code> commands. So we're going to create a new network and then allow the nginx-proxy to communicate via this network.</p>
<p>First we'll create a new network and give it a name of <code>service-tier</code>:</p>
<pre><code>docker network <span class="hljs-operator"><span class="hljs-keyword">create</span> service-<span class="hljs-keyword">tier</span>
</span></code></pre>
<p>Next we'll configure our nginx-proxy container to have access to this network:</p>
<pre><code>docker network <span class="hljs-keyword">connect</span> service-tier nginx-proxy
</code></pre>
<p>Now when we spin up new containers we need to be sure they are also connected to this network or the proxy will not be able to identify them as they come online. This is done in a <a href="https://docs.docker.com/compose/">docker-compose</a> file as seen below.</p>
<h1>Put the two together</h1>
<p>Now that we've defined our application with the <code>server.js</code> and <code>Dockerfile</code> and we have a <code>nginx-proxy</code> ready to proxy to our environment-specific docker http servers, we're going to use <code>docker-compose</code> to help build our container and glue the parts together as well as pass environment variables through to create multiple deployment environments.</p>
<p>Save this file as <code>docker-compose.yml</code></p>
<pre><code><span class="hljs-attribute">version</span>: <span class="hljs-string">'2'</span>

<span class="haml">services:
  web:
    build: ./app/
    environment:
      -<span class="ruby"> <span class="hljs-constant">NODE_ENV</span>=<span class="hljs-variable">${</span><span class="hljs-constant">NODE_ENV</span>}
</span>      -<span class="ruby"> <span class="hljs-constant">PORT</span>=<span class="hljs-variable">${</span><span class="hljs-constant">PORT</span>}
</span>      -<span class="ruby"> <span class="hljs-constant">VIRTUAL_HOST</span>=<span class="hljs-variable">${</span><span class="hljs-constant">VIRTUAL_HOST</span>}
</span>      -<span class="ruby"> <span class="hljs-constant">VIRTUAL_PORT</span>=<span class="hljs-variable">${</span><span class="hljs-constant">PORT</span>}
</span>    ports:
      -<span class="ruby"> <span class="hljs-string">"127.0.0.1:${PORT}:80"</span>
</span>
networks:
  default:
    external:
      name: service-tier
</span></code></pre>
<p>This file is all about:</p>
<ol>
<li>The <code>build: ./app/</code> is the directory where our <code>Dockerfile</code> build is.</li>
<li>The list of <code>environment</code> variables are important. The <code>VIRTUAL_HOST</code> and <code>VIRTUAL_PORT</code> are used by the nginx-proxy to know what port to proxy requests for and at what host/domain name. (We'll show an example later) You can see an earlier exploratory post I wrote <a href="https://staxmanade.com/2016/05/how-to-get-environment-variables-passed-through-docker-compose-to-the-containers/">explaining more about environment vars</a>.</li>
<li>The <code>ports</code> example is also important. We don't want to access the container by going <code>my-docker-test-site.com:8001</code> or whatever port we're actually running the container on because we want to use the <code>VIRTUAL_HOST</code> feature of nginx-proxy to allow us to say <code>qa.my-docker-test-site.com</code>. This configuration sets it up to only listen on the loopback network so the nginx-proxy can proxy to these containers but they aren't accessible from the inter-webs.</li>
<li>Lastly the <code>networks:</code> we define a <code>default</code> network for the web app to use the <code>service-tier</code> that we setup earlier. This allows the nginx-proxy and our running instances of the web container to correctly talk to each other. (I actually have no idea what I'm saying  here - but it is simple enough to setup and I think it's all good - so I'm going with it for now...)</li>
</ol>
<h1>Now what?</h1>
<p>So with all of these pieces in place, all we need to do now is run some docker-compose commands to spin up our necessary environments.</p>
<p>Below is an example script that can be used to spin up <code>qa</code>, and <code>prod</code> environments.</p>
<pre><code>BASE_SITE=my-docker-test-site.com

<span class="hljs-comment"># qa</span>
<span class="hljs-built_in">export</span> NODE_ENV=qa
<span class="hljs-built_in">export</span> PORT=<span class="hljs-number">8001</span>
<span class="hljs-built_in">export</span> VIRTUAL_HOST=<span class="hljs-variable">$NODE_ENV</span>.<span class="hljs-variable">$BASE_SITE</span>
docker-compose -p <span class="hljs-variable">${VIRTUAL_HOST}</span> up <span class="hljs-operator">-d</span>


<span class="hljs-comment"># prod</span>
<span class="hljs-built_in">export</span> NODE_ENV=production
<span class="hljs-built_in">export</span> PORT=<span class="hljs-number">8003</span>
<span class="hljs-built_in">export</span> VIRTUAL_HOST=<span class="hljs-variable">$BASE_SITE</span>
docker-compose -p <span class="hljs-variable">${VIRTUAL_HOST}</span> up <span class="hljs-operator">-d</span>
</code></pre>
<p>This script is <a href="https://staxmanade.com/2016/05/how-to-get-environment-variables-passed-through-docker-compose-to-the-containers/">setting some environment variables</a> that are then used by the <code>docker-compose</code> command where and we're also setting a unique <strong>project name</strong> with <code>-p ${VIRTUAL_HOST}</code>.</p>
<h1>Project Name</h1>
<p>What we said just before this headline is a key part to this. What enables us to run essentially the same project (docker-compose/Dockerfile) but with different environment variables that define things like <code>qa</code> vs <code>prod</code> is when we run <code>docker-compose</code> we're also passing in a <code>-p</code> or <code>--project-name</code> parameter. This allows us to create multiple container instances with different environment variables that all run on <strong>different ports</strong> and in theory isolate themselves from the other environments.</p>
<p>The thinking here is you could have a single <code>docker-compose.yml</code> file that has multiple server definitions like say a <code>nodejs web</code>, <code>couchdb</code>, and <code>redis</code> database all running isolated within their environment.  You can then use the environment variables to drive various items such as feature-toggling newly developed features in a <code>qa</code> environment, but are not necessarily ready to run in a production environment.</p>
<h1>Running/testing this out locally</h1>
<p>You probably want to play with this idea and test it out locally before trying to push it to a remote system.</p>
<p>One easy way to do this is to modify your <code>/etc/hosts</code> file (on *nix) or follow <a href="http://www.howtogeek.com/howto/27350/beginner-geek-how-to-edit-your-hosts-file/">this on windows</a> to map the specific domain names you have setup for your environments to the actual service running docker. This will allow the <code>nginx-proxy</code> to do it's magic.</p>
<p>I'm currently still using <code>docker-machine</code> to run my docker environment in a VirtualBox VM so my <code>/etc/hosts</code> file looks like this.</p>
<pre><code><span class="hljs-preprocessor">##</span>
<span class="hljs-preprocessor"># Host Database</span>
<span class="hljs-preprocessor">#</span>
<span class="hljs-preprocessor"># localhost is used to configure the loopback interface</span>
<span class="hljs-preprocessor"># when the system is booting.  Do not change this entry.</span>
<span class="hljs-preprocessor">##</span>
<span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>	localhost
<span class="hljs-number">255.255</span><span class="hljs-number">.255</span><span class="hljs-number">.255</span>	broadcasthost
::<span class="hljs-number">1</span>             localhost

<span class="hljs-number">192.168</span><span class="hljs-number">.99</span><span class="hljs-number">.100</span> qa.my-docker-test-site.com
<span class="hljs-number">192.168</span><span class="hljs-number">.99</span><span class="hljs-number">.100</span> stage.my-docker-test-site.com
<span class="hljs-number">192.168</span><span class="hljs-number">.99</span><span class="hljs-number">.100</span> my-docker-test-site.com

</code></pre>
<p>If you have the docker containers running that we've worked through so far (for all environments) we should be able to visit <code>qa.my-docker-test-site.com</code> in the browser and hopefully get this:</p>
<pre><code>Hello World!

<span class="hljs-label">VIRTUAL_HOST:</span> qa.my-docker-test-site.com
<span class="hljs-label">NODE_ENV:</span> qa
<span class="hljs-label">PORT:</span> <span class="hljs-number">8001</span>
</code></pre>
<p>Also try out the production environment at <code>my-docker-test-site.com</code> to verify it is working as expected.</p>
<p><strong>THIS IS AWESOME :)</strong> I was actually quite happy to traveled this far in this exploration. But now let's try to take it up a notch and deploy what we just built locally to the DigitalOcean in the cloud (<img class="emoji" title="cloud" alt="cloud" src="https://assets-cdn.github.com/images/icons/emoji/unicode/2601.png" height="20" width="20" align="absmiddle">).</p>
<h1>Deploy to the Cloud!</h1>
<p>Now how do we get this locally running multi-environment system up to a server in the cloud?</p>
<p>Just tonight while researching options I found this simple set of steps to get it going on DigitalOcean. I say simple because you should the original steps I was going to try and use to deploy this... sheesh.</p>
<p>These are the steps we're going to walk through.</p>
<ol>
<li>Get an Account @ <a href="https://m.do.co/c/451940554550">DigitalOcean</a></li>
<li>Create a Docker Droplet (this was way-cool)</li>
<li>Build and Deploy our nginx-proxy.</li>
<li>Build and Deploy our App</li>
<li>Configure our DNS (domain name)</li>
<li>Profit!</li>
</ol>
<p>Tonight I discovered this <a href="https://docs.docker.com/machine/examples/ocean/">blog post</a> on docker that describes using <a href="https://docs.docker.com/machine/">docker-machine</a> with the <a href="https://docs.docker.com/machine/drivers/digital-ocean/">digitalocean driver</a> to do basically everything we did above - but IN THE CLOUD <img class="emoji" title="cloud" alt="cloud" src="https://assets-cdn.github.com/images/icons/emoji/unicode/2601.png" height="20" width="20" align="absmiddle"> - kind of blew me away actually.</p>
<h2>Get an Account</h2>
<p>First make sure you've signed up with a <a href="https://m.do.co/c/451940554550">DigitalOcean</a> and are signed in.</p>
<h2>Create a Docker Droplet (this was way-cool)</h2>
<p>Next we're going to use a cool feature of <a href="https://docs.docker.com/machine/">docker-machine</a> where we can leverage the <a href="https://docs.docker.com/machine/drivers/digital-ocean/">DigitalOcean driver</a> to help us create and manage our docker images.</p>
<p>Complete <code>Step 1</code> and <code>Step 2</code> in the following post <a href="https://docs.docker.com/machine/examples/ocean/">DigitalOcean example</a> to acquire a DigitalOcean personal access token.</p>
<p>Now that you have your DigitalOcean api token, you do right? Either pass it direclty into the below command (in place of <code>$DOTOKEN</code> or set a local var as demonstrated.</p>
<pre><code>DOTOKEN=XXXX &lt;-- your token there...
docker-machine create --driver digitalocean --digitalocean-access-token <span class="hljs-variable">$DOTOKEN</span> docker-multi-environment
</code></pre>
<blockquote>
<p>NOTE: There was an issue where (this used to work but stopped with the the docker-machine DigitalOcean default image <a href="https://github.com/docker/machine/issues/3394">reported here</a>). To work around this try using a different image name</p>
</blockquote>
<p>EX:</p>
<pre><code>DIGITALOCEAN_IMAGE=<span class="hljs-string">"ubuntu-16-04-x64"</span>
docker-machine create --driver digitalocean --digitalocean-access-token <span class="hljs-variable">$DOTOKEN</span> docker-multi-environment
</code></pre>
<p>If you refreshed your DigitalOcean's <a href="https://cloud.digitalocean.com/droplets">droplets page</a> you should see a new droplet called <code>docker-multi-environment</code>.</p>
<p>We can now configure our local terminal to allow all docker commands to run against this remotely running docker environment on our newly created droplet.</p>
<pre><code><span class="hljs-keyword">eval</span> <span class="hljs-variable">$(</span>docker-machine <span class="hljs-keyword">env</span> docker-multi-environment)
</code></pre>
<p>If you ran <code>docker ps</code> it should be empty, but this is literally listing the containers that are running up at DigitalOceain in our droplet. How awesome is that?</p>
<h2>Build and Deploy our nginx-proxy.</h2>
<p>Now that we can just speak <code>docker</code> in the cloud, run the following commands - these are all assuming we're executing them against the DigitalOcean droplet in the <img class="emoji" title="cloud" alt="cloud" src="https://assets-cdn.github.com/images/icons/emoji/unicode/2601.png" height="20" width="20" align="absmiddle">!!</p>
<ol>
<li>
<p>Spin up our remote <code>nginx-proxy</code> on the remote droplet</p>
<pre><code>docker run -d -<span class="hljs-tag">p</span> <span class="hljs-number">80</span>:<span class="hljs-number">80</span> --name nginx-proxy -v /var/run/docker<span class="hljs-class">.sock</span>:/tmp/docker<span class="hljs-class">.sock</span>:ro jwilder/nginx-proxy
</code></pre>
</li>
<li>
<p>Create our network</p>
<pre><code>docker network <span class="hljs-operator"><span class="hljs-keyword">create</span> service-<span class="hljs-keyword">tier</span>
</span></code></pre>
</li>
<li>
<p>Tell <code>nginx-proxy</code> about this network</p>
<pre><code>docker network <span class="hljs-keyword">connect</span> service-tier nginx-proxy
</code></pre>
</li>
</ol>
<h2>Build and Deploy our App</h2>
<p>I know this post has gotten a bit long, but if you've made it this far we're almost there...</p>
<p>If you were to run the following script in our local project's folder where we have the <code>docker-compose.yml</code> file:</p>
<blockquote>
<p>Be sure to update <code>BASE_SITE=my-docker-test-site.com</code> with your domain name or sub-domain like <code>BASE_SITE=multi-env.my-docker-test-site.com</code></p>
</blockquote>
<pre><code>BASE_SITE=my-docker-test-site.com

<span class="hljs-comment"># qa</span>
<span class="hljs-built_in">export</span> NODE_ENV=qa
<span class="hljs-built_in">export</span> PORT=<span class="hljs-number">8001</span>
<span class="hljs-built_in">export</span> VIRTUAL_HOST=<span class="hljs-variable">$NODE_ENV</span>.<span class="hljs-variable">$BASE_SITE</span>
docker-compose -p <span class="hljs-variable">${VIRTUAL_HOST}</span> up <span class="hljs-operator">-d</span>


<span class="hljs-comment"># prod</span>
<span class="hljs-built_in">export</span> NODE_ENV=production
<span class="hljs-built_in">export</span> PORT=<span class="hljs-number">8003</span>
<span class="hljs-built_in">export</span> VIRTUAL_HOST=<span class="hljs-variable">$BASE_SITE</span>
docker-compose -p <span class="hljs-variable">${VIRTUAL_HOST}</span> up <span class="hljs-operator">-d</span>
</code></pre>
<p>You should now be able to run <code>docker ps</code> or <code>docker-compose ps</code> and see 3 containers running. The <code>nginx-proxy</code>, your <code>qa</code> site and also the <code>prod</code> site.</p>
<p>All that's left is to make sure DNS is configured and pointing to our <code>nginx-proxy</code> front-end...</p>
<p>While playing with this - I kept tearing down droplets and re-building them as I worked through this tutorial and I kept forgetting to adjust my DNS settings. However right in the middle of writing this tutorial DigitalOcean came out with <a href="https://www.digitalocean.com/community/tutorials/how-to-use-floating-ips-on-digitalocean">Floating Ip's</a> which wasn't perfect, but definitely made this easier to work with. I didn't have to always update the IP address of my droplet, but instead just update the floating ip to point to the newly created droplet.</p>
<h2>Configure our DNS (domain name)</h2>
<p>I'm assuming you've already purchased a domain name that you can setup and configure on DigitalOcean. So I don't want to go too far into this process.</p>
<p>I also think DNS is out of scope for this post (as there are many others who can do a better job) but I used some great resources such as these while configuring my DigitalOcean setup.</p>
<ul>
<li><a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-a-host-name-with-digitalocean">How To Set Up a Host Name with DigitalOcean</a></li>
<li><a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-and-test-dns-subdomains-with-digitalocean-s-dns-panel">How To Set Up and Test DNS Subdomains with DigitalOcean's DNS Panel</a></li>
</ul>
<h1>Environment All Things</h1>
<p>If you've made it this far, you hopefully have a DigitalOcean droplet that is now serving <code>qa</code> and <code>prod</code> http requests.</p>
<p>NICE!!!</p>
<p>Now the most important thing - how to seamlessly update an environment with a new build...</p>
<h1>Let's make an update to QA.</h1>
<p>Now that we've deployed our site to QA and to walk through this a little further, let's make a modification to our <code>qa</code> site and see if we can get it deployed without causing any downtime especially to the <code>prod</code> site, but maybe we can also get an in-place deployment done and have little-to-no down time in <code>qa</code> as well.</p>
<p>I wrote that paragraph above the other night near bedtime and as I'm learning some of this on the fly had no idea if this would be easy enough to accomplish, but to my surprise deploying an update to <code>qa</code> was a piece of cake.</p>
<p>For this test I made a simple change to my node web server code so I could easily see that the change was deployed (or not).</p>
<p>I turned <code>Hello World!</code> into <code>Hello World! V2</code> below.</p>
<p>File: <code>./app/server.js</code></p>
<pre><code><span class="hljs-keyword">var</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">'http'</span>);

<span class="hljs-keyword">var</span> server = http.createServer(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>)</span>{
    res.writeHead(<span class="hljs-number">200</span>, {<span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"text/plain"</span>});
    res.end(<span class="hljs-string">`
Hello World!

VIRTUAL_HOST: <span class="hljs-subst">${process.env.VIRTUAL_HOST}</span>
NODE_ENV: <span class="hljs-subst">${process.env.NODE_ENV}</span>
PORT: <span class="hljs-subst">${process.env.PORT}</span>

`</span>.split(<span class="hljs-string">'/n'</span>).join(<span class="hljs-string">'&lt;br&gt;'</span>));
});

server.listen(<span class="hljs-number">80</span>);
</code></pre>
<p>I then used <code>docker-compose</code> to bring up another &quot;environment&quot; but using the same <code>qa</code> <code>VIRTUAL_HOST</code> as before.</p>
<pre><code>BASE_SITE=my-docker-test-site.com

export NODE_ENV=qa
export PORT=<span class="hljs-number">8004</span>
export VIRTUAL_HOST=<span class="hljs-variable">$NODE</span>_ENV.<span class="hljs-variable">$BASE</span>_SITE
docker-compose -p ${VIRTUAL_HOST}x2 up -d
</code></pre>
<blockquote>
<p>NOTICE: how the <code>-p</code> parameter we added <code>x2</code> (just to give it a different project name (for being a different version)).</p>
</blockquote>
<p>This will bring up another docker container with our updated web application and to my surprise the nginx-proxy automatically chose this new container to send requests to.</p>
<p>So if you <code>docker ps</code> you should see 4 containers running. 1 nginx-proxy, 1 prod container, 2 qa containers (with different names).</p>
<p>You can think about leaving both containers running for the moment while  you test out the new release.</p>
<p>One neat thing you can think about with this is if there was something seriously wrong with the new qa release you could just stop the new container and (<code>docker stop &lt;new_container_id&gt;</code>) and the proxy will start redirecting back to the old qa container. (That only works of course if your deployment was immutable - meaning you didn't have the new container run some one way database migration script... but that's not something I want to think about or cover in this post).</p>
<p>Once you're comfortable running the new version you can now bring down and cleanup the older version.</p>
<pre><code>docker <span class="hljs-keyword">ps</span> # <span class="hljs-keyword">to</span> <span class="hljs-keyword">list</span> the containers running
docker <span class="hljs-keyword">stop</span> &lt;old_qa_container_id&gt;

docker images # <span class="hljs-keyword">to</span> <span class="hljs-keyword">list</span> the images we have <span class="hljs-keyword">on</span> our instance
docker rmi &lt;old_qa_image_id&gt;
</code></pre>
<h1>Now let completely remove our test...</h1>
<p>You probably don't want to run the sample node script from above forever as you'll be charged some money from DigitalOcean for this and I'd feel bad if you received a bill for this little test beyond a few pennies as you test it out...</p>
<p>The following command will completely remove the droplet from DigitalOcean.</p>
<pre><code><span class="hljs-label">docker</span>-machine rm docker-<span class="hljs-keyword">multi-environment
</span></code></pre>
<h1>Wrap Up and What's Next?</h1>
<p>I feel like I've done enough learning and sharing in this post. But there is still more to do...</p>
<p>If you want to check out the snippets above combined into a sample github repository I've put it <a href="https://github.com/staxmanade/sample-docker-compose-multiple-environment.git">up here</a>.</p>
<h1>Future thinking...</h1>
<p>I don't know if I'll blog about these, but I definitely want to figure them out. If you find a way to extend my sample above to include the following I'd love to hear about it...</p>
<ul>
<li>SSL (consider cloudflare or letsencrypt?)</li>
<li>Easy way to secure the qa/stage environments?</li>
</ul>
<p>Happy Docker Enviornment Building!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Easily simulate slow async calls using JavaScript async/await]]></title>
        <id>https://staxmanade.com/2016/07/easily-simulate-slow-async-calls-using-javascript-async-await/</id>
        <link href="https://staxmanade.com/2016/07/easily-simulate-slow-async-calls-using-javascript-async-await/">
        </link>
        <updated>2016-07-08T12:34:43.041Z</updated>
        <summary type="html"><![CDATA[Recently I wanted to manually and visually test some U.I. that I couldn't easily see because an async operations was happening two fast. (first world ...]]></summary>
        <content type="html"><![CDATA[<p>Recently I wanted to manually and visually test some U.I. that I couldn't easily see because an async operations was happening two fast. (first world problems)</p>
<p>I've really been enjoying the new <code>async/await</code> syntax that can be leveraged in recent JavaScript transpires such as Babel and TypeScript but when it happens so fast on a local development environment, some U.I. interactions could get tough to test out. <strong>So how can we slow this down or more appropriately add some stall time?</strong></p>
<p>As an example, let's say you have the following <code>async</code> javascript method</p>
<pre><code>
<span class="hljs-keyword">var</span> doSomething = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">var</span> data = <span class="hljs-keyword">await</span> someRemoteOperation();
  <span class="hljs-keyword">await</span> doSomethingElse(data);
}

</code></pre>
<p>If the first or second asynchronous methods in the example above were running too fast (as were in my case), I was pleased to see how easy it was to inject a bit of code to manually stall the operation.</p>
<p>The snippet below is short and sweet... this just delays continuous execution of an async operation for 3 seconds.</p>
<pre><code>  await new Promise<span class="hljs-list">(<span class="hljs-keyword">resolve</span> =&gt; setTimeout<span class="hljs-list">(<span class="hljs-keyword">resolve</span>, <span class="hljs-number">3000</span>)</span>)</span><span class="hljs-comment">;</span>

</code></pre>
<h1>The little baby staller helper</h1>
<p>Give it a name and make it a bit more re-usable.</p>
<pre><code><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">stall</span>(<span class="hljs-params">stallTime = 3000</span>) </span>{
  <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(resolve =&gt; setTimeout(resolve, stallTime));
}
</code></pre>
<p>The above helper can be used by just awaiting it (see below)</p>
<pre><code>
<span class="hljs-keyword">var</span> doSomething = <span class="hljs-keyword">async</span> () =&gt; {

  <span class="hljs-keyword">var</span> data = <span class="hljs-keyword">await</span> someRemoteOperation();

  <span class="hljs-keyword">await</span> stall(); <span class="hljs-comment">// stalls for the default 3 seconds</span>
  <span class="hljs-keyword">await</span> stall(<span class="hljs-number">500</span>); <span class="hljs-comment">// stalls for 1/2 a second</span>

  <span class="hljs-keyword">await</span> doSomethingElse(data);

}

</code></pre>
<p>Now we have an <code>async</code> function that runs slower - isn't that what you always wanted?</p>
<p>Happy Stalling!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[One Programmers Letter to his Wife]]></title>
        <id>https://staxmanade.com/2016/06/one-programmers-letter-to-his-wife/</id>
        <link href="https://staxmanade.com/2016/06/one-programmers-letter-to-his-wife/">
        </link>
        <updated>2016-06-29T01:46:02.830Z</updated>
        <summary type="html"><![CDATA[One of my core natures is as a builder and creator. I'm strongly introverted so much of my time is spent in my own head. My best and sometimes worst t...]]></summary>
        <content type="html"><![CDATA[<p>One of my core natures is as a builder and creator. I'm strongly introverted so much of my time is spent in my own head. My best and sometimes worst times are regularly spent by myself. I know you already know many things about introverts, but as a refresher I'd like you to read this.</p>
<blockquote>
<p><a href="http://www.theatlantic.com/magazine/archive/2003/03/caring-for-your-introvert/302696/">Caring for your introvert</a></p>
</blockquote>
<p>As a creator, one of the happiest moments we can experience is getting into a state of &quot;flow&quot;.</p>
<blockquote>
<p>In positive psychology, flow, also known as the zone, is the mental state of operation in which a person performing an activity is fully immersed in a feeling of energized focus, full involvement, and enjoyment in the process of the activity.
<a href="">https://en.wikipedia.org/wiki/Flow_(psychology)</a></p>
</blockquote>
<p>I've heard this flow state described as a process where the mind is so focus on the task at hand, so engulfed in the spirit of the process that all other external processing of our environment and even our own bodily needs can be ignored. The brain puts so much energy and focus into this, that things like the need to eat, sleep, or sometimes even ignoring the restroom (for as long as possible - waiting until my bladder is SCREAMING at me).</p>
<p>I'm quite happy when I'm making progress on my creation(s) as they can often invoke this flow state. While the opposite of the &quot;enjoyment&quot; can certainly happen while working on projects as they can frustrate the heck out of me sometimes and if it ever bleeds into our relationship I'm sorry for that.</p>
<p>I wish I could convey the highs I can experience while in &quot;flow&quot; as strongly as you've likely see my frustrations about the lows. Sadly, without the lows, struggle, up hill battles, cussing at the computer I could possibly never really experience the feelings of success or overcoming that struggle and enjoy them as much as I do.</p>
<p>Between work, family time, children, shopping, housework, sleep and whatever else we fill our days with, it often times feels like I get to apply very little time to this thing that I am truly driven (maybe slightly addicted to) and excited about.</p>
<p>I know you try to give me time to work on these things. There are times you think you've given a Saturday morning or an evening for me to work on my thing. However, sadly for it to truly be a successful session, I need time and space with room to concentrate. An hour before bedtime makes me feel like I shouldn't even try, because it could take at least 30-40 min to get back into the project leaving so little time to be productive that it's not even worth starting. These are times when I decide to blow any amount of time I've been given and just waste it watching a show on Netflix. Not because I don't want to work on my thing, but because I know the amount of effort it will take to get into the flow state will take far too long to make it worth it. If I were to get into flow, I'm then going to want to stay there and likely push past my bed time (which is getting harder and harder to recover from).</p>
<p>I don't want this to sound like this creation/building thing is more important than my family. In fact it's not. If you look at my actions and track record, the amount of time I have pushed aside so I could help you with your endeavors by watching kids, taking on extra shopping trips, house duties as well as the financial obligation (and strain), and still finding time to spend with you in the evenings at the expense of this thing I want to do should prove that my commitment to the family (and you) is still a priority.</p>
<p>I don't know how to close this out an wrap it up, other than to say I love you. I love my children. I also love what I build. I would like to work with you to find a way to balance these items a little better.</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Reusable React Component with Overridable Inline CSS Styles]]></title>
        <id>https://staxmanade.com/2016/06/reusable-react-component-with-overridable-inline-css-styles/</id>
        <link href="https://staxmanade.com/2016/06/reusable-react-component-with-overridable-inline-css-styles/">
        </link>
        <updated>2016-06-21T21:31:22.600Z</updated>
        <summary type="html"><![CDATA[React's Component model is great at allowing the component creator to define the interface that consumers of the component interact with. (What is exp...]]></summary>
        <content type="html"><![CDATA[<p>React's Component model is great at allowing the component creator to define the interface that consumers of the component interact with. (What is exposed vs what is abstracted away).</p>
<p>If you're building a component and using any in-line styles and you're not careful you can lock the consumer of your component out of potential customizations they may require for their specific use-case (that you can't think of or foresee). Trying to build components to be reusable and a little more <a href="https://en.wikipedia.org/wiki/Open/closed_principle">OCP</a> can be challenging especially with how difficult it can be to get css layouts the way you (or the consumer of your component) may want...</p>
<p>As an example, let's create simple <code>img</code> component to illustrate the point.</p>
<p>Let's say we have the following image component.</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-type">React</span> from <span class="hljs-symbol">'reac</span>t';

export <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Image</span> <span class="hljs-keyword"><span class="hljs-keyword">extends</span></span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> {</span>

  render() {
    <span class="hljs-keyword">return</span> (
      &lt;div&gt;
        &lt;img src={<span class="hljs-keyword">this</span>.props.src} /&gt;
      &lt;/div&gt;
    );
  }

}
</code></pre>
<p>The above component is very simple and very specific.</p>
<p>Now let's say we allow our consumers to customize the height or width of the image. You may think, ok, simple we'll just allow the consumer to specify <code>height</code> and <code>width</code> as props to the component.</p>
<p>So the consumer could just go <code>&lt;Image height=&quot;20&quot; width=&quot;20&quot; src=&quot;someimage.png&quot; /&gt;</code>.</p>
<p>And you end up with something that could look like this.</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-type">React</span> from <span class="hljs-symbol">'reac</span>t';

export <span class="hljs-keyword">default</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Image</span> <span class="hljs-keyword"><span class="hljs-keyword">extends</span></span> <span class="hljs-title">React</span>.<span class="hljs-title">Component</span> {</span>

  render() {
    let imageStyle = {
      height: <span class="hljs-keyword">this</span>.props.height,
      width: <span class="hljs-keyword">this</span>.props.width
    };
    <span class="hljs-keyword">return</span> (
      &lt;div&gt;
        &lt;img src={<span class="hljs-keyword">this</span>.props.src} style={imageStyle} /&gt;
      &lt;/div&gt;
    );
  }
}
</code></pre>
<p>Now this works for a while, the consumers of your component are happy they can control the <code>height</code> and <code>width</code> and everyone's humming along merrily.</p>
<p>Then someone comes to you and says they are having some layout issues and need to control something like <code>float</code>, or <code>margin</code>, or <code>padding</code>... This idea of extending the component with more props could become cumbersome if we have to do this for each and every potential layout option available.</p>
<p>How could we extend this generic pattern into something that allows the component to define a general set of happy defaults, while still giving the consumer complete control over layout?</p>
<h1>One Possible Solution</h1>
<p>We can use something like <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign">Object.assign()</a> to easily accomplish this.</p>
<p>We can allow the consumers to pass in their own <code>style={...}</code> property and provide a set of sensible defaults for the component, but allow the consumer of our component to completely override a style if necessaryl</p>
<p>We can update our:</p>
<pre><code>    let imageStyle = {
      <span class="hljs-variable">height</span>: <span class="hljs-keyword">this</span>.props.<span class="hljs-variable">height</span>,
      <span class="hljs-variable">width</span>: <span class="hljs-keyword">this</span>.props.<span class="hljs-variable">width</span>
    };
</code></pre>
<p>to the following pattern:</p>
<pre><code>    <span class="hljs-keyword">let</span> imageStyle = Object.<span class="hljs-keyword">assign</span>(
      {},								<span class="hljs-comment">// target (starting with)</span>
      { ...sensible defaults... },	<span class="hljs-comment">// some pre-defined default React inline-style for the component</span>
      <span class="hljs-keyword">this</span>.props.style				<span class="hljs-comment">// allow consumers to override properties</span>
    );
</code></pre>
<p>Now if the consumer calls the component with <code>&lt;Image style={{height: &quot;21px&quot;, width: &quot;21px&quot;}} src=&quot;someImage.png&quot; /&gt;</code> the component's consumers' values will override any defaults provided. And they can extend the style with anything else they may need.</p>
<p>Happy Componentization!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Strange error on docker-compose up: oci runtime error: exec format error]]></title>
        <id>https://staxmanade.com/2016/05/strange-error-on-docker-compose-up/</id>
        <link href="https://staxmanade.com/2016/05/strange-error-on-docker-compose-up/">
        </link>
        <updated>2016-05-27T20:18:56.884Z</updated>
        <summary type="html"><![CDATA[I ran into a non-intuitive error while mucking around with [docker-compose](https://docs.docker.com/compose/) recently on [an example](https://staxman...]]></summary>
        <content type="html"><![CDATA[<p>I ran into a non-intuitive error while mucking around with <a href="https://docs.docker.com/compose/">docker-compose</a> recently on <a href="https://staxmanade.com/2016/05/how-to-get-environment-variables-passed-through-docker-compose-to-the-containers/">an example</a>.</p>
<h1>docker-compose up</h1>
<pre><code>Building some_server
Step 1 : FROM alpine
 -<span class="ruby">--&gt; <span class="hljs-number">13</span>e1761bf172
</span>Step 2 : ENV DEMO_VAR WAT
 -<span class="ruby">--&gt; <span class="hljs-constant">Using</span> cache
</span> -<span class="ruby">--&gt; <span class="hljs-number">378</span>dbaa4a048
</span>Step 3 : COPY docker-entrypoint.sh /
 -<span class="ruby">--&gt; e5962cef9382
</span>Removing intermediate container 43fa24c31444
Step 4 : ENTRYPOINT /docker-entrypoint.sh
 -<span class="ruby">--&gt; <span class="hljs-constant">Running</span> <span class="hljs-keyword">in</span> <span class="hljs-number">5</span>a2e19bf7a45
</span> -<span class="ruby">--&gt; <span class="hljs-number">331</span>d2648d969
</span>Removing intermediate container 5a2e19bf7a45
Successfully built 331d2648d969
Recreating exampleworkingdockercomposeenvironmentvars_some_server_1
</code></pre>
<h1>The Error</h1>
<pre><code>ERROR: for some_server  rpc error: code = 2 desc = "oci runtime error: exec format error"
Traceback (most recent <span class="hljs-operator"><span class="hljs-keyword">call</span> <span class="hljs-keyword">last</span>):
  <span class="hljs-keyword">File</span> <span class="hljs-string">"&lt;string&gt;"</span>, line <span class="hljs-number">3</span>, <span class="hljs-keyword">in</span> &lt;<span class="hljs-keyword">module</span>&gt;
  <span class="hljs-keyword">File</span> <span class="hljs-string">"compose/cli/main.py"</span>, line <span class="hljs-number">63</span>, <span class="hljs-keyword">in</span> <span class="hljs-keyword">main</span>
AttributeError: <span class="hljs-string">'ProjectError'</span> <span class="hljs-keyword">object</span> has <span class="hljs-keyword">no</span> <span class="hljs-keyword">attribute</span> <span class="hljs-string">'msg'</span>
docker-compose returned -<span class="hljs-number">1</span>
</span></code></pre>
<h1>The Actual Problem and Solution:</h1>
<p>I had a <code>Dockerfile</code> that used an entrypoint that looked like <code>ENTRYPOINT [&quot;/docker-entrypoint.sh&quot;]</code>.</p>
<p>The real problem was the <code>docker-entrypoint.sh</code> script was missing a <a href="https://en.wikipedia.org/wiki/Shebang_(Unix)">#shebang</a>.</p>
<p>So changing this</p>
<pre><code><span class="hljs-built_in">echo</span> <span class="hljs-string">"ENV Var Passed in: <span class="hljs-variable">$DEMO_VAR</span>"</span>
</code></pre>
<p>to this</p>
<pre><code><span class="hljs-shebang">#!/bin/sh</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"ENV Var Passed in: <span class="hljs-variable">$DEMO_VAR</span>"</span>
</code></pre>
<p>solved my issue!</p>
<p>Also note it'll depend on the base image <code>FROM &lt;some linux distro&gt;</code> that may change what you're required #shebang should be.</p>
<p>Whew!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[How to Get Environment Variables Passed Through docker-compose to the Containers]]></title>
        <id>https://staxmanade.com/2016/05/how-to-get-environment-variables-passed-through-docker-compose-to-the-containers/</id>
        <link href="https://staxmanade.com/2016/05/how-to-get-environment-variables-passed-through-docker-compose-to-the-containers/">
        </link>
        <updated>2016-05-26T04:36:41.974Z</updated>
        <summary type="html"><![CDATA[I've been playing with a [little toy](https://github.com/staxmanade/sample-pouch-couch-databaseperuser) that uses [docker-compose](https://docs.docker...]]></summary>
        <content type="html"><![CDATA[<p>I've been playing with a <a href="https://github.com/staxmanade/sample-pouch-couch-databaseperuser">little toy</a> that uses <a href="https://docs.docker.com/compose">docker-compose</a> to bring together a web app, couchdb, and redis container into an easy-ier-ish cohesive unit.</p>
<p>While working on it (and to make it a bit more generic), my next step was to find a way to pass the database admin user/pass (and other configuraiton options) into the containers as <strong>environment variables</strong> which took me way longer to figure out than it should have...</p>
<p>Hopefully this posts helps it click for you a little faster than it (didn't) for me :)</p>
<p>If you land here, you've likely already poured over the different parts of documentation for docker, docker-compose and environment variables.</p>
<p>Things like:</p>
<ul>
<li><a href="https://docs.docker.com/compose/compose-file/#variable-substitution">https://docs.docker.com/compose/compose-file/#variable-substitution</a></li>
<li><a href="https://docs.docker.com/compose/compose-file/#env-file">https://docs.docker.com/compose/compose-file/#env-file</a></li>
<li><a href="http://stackoverflow.com/questions/29377853/how-to-use-environment-variables-in-docker-compose">http://stackoverflow.com/questions/29377853/how-to-use-environment-variables-in-docker-compose</a></li>
<li>Google: <a href="http://lmgtfy.com/?q=docker-compose+environment+variables">docker-compose environment variables</a></li>
</ul>
<p>In case things drift in the product or docs, this post was written using <code>docker-compose version 1.7.1, build 0a9ab35</code> so keep that in mind...</p>
<p>I think the difficult thing for me was piecing the various ways you can get environment variables defined and the necessary mapping required within the <code>docker-compose</code> file.</p>
<h1>Environment Variable Setup Stages.</h1>
<p>For me it didn't click until I was able to think about the stages that needed to exist for an environment variable to go from the development computer -&gt; to the -&gt; docker container.</p>
<p>For now I'm thinking of using the following model...</p>
<pre><code>
 ------------------------       --------------------       ------------------
|<span class="hljs-string">   Env Source           </span>|<span class="hljs-string">     </span>|<span class="hljs-string"> docker-compose.yml </span>|<span class="hljs-string">     </span>|<span class="hljs-string"> Docker Container </span>|
|<span class="hljs-string">                        </span>|<span class="hljs-string">     </span>|<span class="hljs-string">                    </span>|<span class="hljs-string">     </span>|<span class="hljs-string">                  </span>|
|<span class="hljs-string">   A) .env file         </span>|<span class="hljs-string"> --&gt; </span>|<span class="hljs-string"> map env vars using </span>|<span class="hljs-string"> --&gt; </span>|<span class="hljs-string"> echo $DEMO_VAR   </span>|
|<span class="hljs-string">   B) run-time terminal </span>|<span class="hljs-string">     </span>|<span class="hljs-string"> interpolation      </span>|<span class="hljs-string">     </span>|<span class="hljs-string">                  </span>|
|<span class="hljs-string">       env var          </span>|<span class="hljs-string">     </span>|<span class="hljs-string"> in this file.      </span>|<span class="hljs-string">     </span>|<span class="hljs-string">                  </span>|
 ------------------------      ---------------------       ------------------
</code></pre>
<h1>A working example.</h1>
<p>If you want to see all of this in one place <a href="https://github.com/staxmanade/example-working-docker-compose-environment-vars">check out this github example</a> which is outline below.</p>
<p>The example above is layed out like so...</p>
<pre><code>.
|<span class="hljs-string">____.env
</span>|<span class="hljs-string">____docker-compose.yml
</span>|<span class="hljs-string">____env-file-test
</span>|<span class="hljs-string"> </span>|<span class="hljs-string">____docker-entrypoint.sh
</span>|<span class="hljs-string"> </span>|____Dockerfile
|<span class="hljs-string">____README.md
</span></code></pre>
<h1>The <code>.env</code> file:</h1>
<p>This is where you can place each of the environment variables you need in here.</p>
<pre><code>DEMO_VAR=Test <span class="hljs-built_in">value</span> <span class="hljs-built_in">from</span> .env <span class="hljs-built_in">file</span>!
</code></pre>
<p>As the <a href="https://docs.docker.com/compose/compose-file/#env-file">docs say</a> you can use <code># as comments</code> and blank lines in the file - all other lines must be in the format of <code>ENV_VAR=ENV_VALUE</code>.</p>
<p><img class="emoji" title="warning" alt="warning" src="https://assets-cdn.github.com/images/icons/emoji/unicode/26a0.png" height="20" width="20" align="absmiddle"> environment variables in your terminal's context will take president over the values in the <code>.env</code> file. <img class="emoji" title="warning" alt="warning" src="https://assets-cdn.github.com/images/icons/emoji/unicode/26a0.png" height="20" width="20" align="absmiddle"></p>
<h1>The <code>docker-compose.yml</code>:</h1>
<pre><code><span class="hljs-keyword">version</span>: <span class="hljs-string">"2"</span>
services:
  some_server:
    build: ./env-<span class="hljs-keyword">file</span>-<span class="hljs-keyword">test</span>
    environment:
     - DEMO_VAR=<span class="hljs-label">${DEMO_VAR}</span>
</code></pre>
<p>The above file is the part where I got tripped up, and once I added the <code>environment:</code> section it all clicked.</p>
<p>You likely don't want every one of your development or production server's environment variables to show up inside your container. This file acts a bit like the <code>docker run -e ENV_VAR=FOO</code> option and allows you to select specific environment variables that are to be passed into the container.</p>
<p>I like the declarative approach of this file as it makes environment variable dependencies explicit.</p>
<h1>The <code>env-file-test/Dockerfile</code>:</h1>
<pre><code><span class="hljs-built_in">FROM</span> alpine

<span class="hljs-built_in">ENV</span> DEMO_VAR WAT

<span class="hljs-built_in">COPY</span> <span class="bash">docker-entrypoint.sh /
</span><span class="hljs-built_in">ENTRYPOINT</span> <span class="bash">[<span class="hljs-string">"/docker-entrypoint.sh"</span>]
</span></code></pre>
<p>Pretty standard <code>Dockerfile</code>, but one thing I learned is you can setup default environment variables using the <a href="https://docs.docker.com/engine/reference/builder/#env">docker <code>ENV</code></a> directive. But these will be overriden by the <code>.env</code> file or variables in your terminal's environment.</p>
<h1>The <code>env-file-test/docker-entrypoint.sh</code></h1>
<pre><code><span class="hljs-shebang">#!/bin/sh</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"ENV Var Passed in: <span class="hljs-variable">$DEMO_VAR</span>"</span>
</code></pre>
<p>This was just a sample script to print out the environment variable.</p>
<h1>Some other things I learned</h1>
<p><img class="emoji" title="warning" alt="warning" src="https://assets-cdn.github.com/images/icons/emoji/unicode/26a0.png" height="20" width="20" align="absmiddle"> The docs say you can specify your own <code>env-file</code> or even multiple files, however I could not get that working. It always wanted to choose the <code>.env</code> file.</p>
<p><img class="emoji" title="warning" alt="warning" src="https://assets-cdn.github.com/images/icons/emoji/unicode/26a0.png" height="20" width="20" align="absmiddle"> Also note: that if you have an environment variable specified in your terminal that also exists in your <code>.env</code> file the terminal's environment takes precedence over the <code>.env</code> file. <img class="emoji" title="warning" alt="warning" src="https://assets-cdn.github.com/images/icons/emoji/unicode/26a0.png" height="20" width="20" align="absmiddle"></p>
<p>Happy Environment Setup!</p>
]]></content>
    </entry>
    <entry>
        <title type="html"><![CDATA[Configuring Git to Use Different Name and Email Depending on Folder Context]]></title>
        <id>https://staxmanade.com/2016/05/configuring-git-to-use-different-name-and-email-depending-on-folder-context/</id>
        <link href="https://staxmanade.com/2016/05/configuring-git-to-use-different-name-and-email-depending-on-folder-context/">
        </link>
        <updated>2016-05-25T22:16:39.455Z</updated>
        <summary type="html"><![CDATA[Thought I'd share how I'm configuring `user.name` and `user.email` for git on my work computer. This is really just a post so when I forget how I did ...]]></summary>
        <content type="html"><![CDATA[<p>Thought I'd share how I'm configuring <code>user.name</code> and <code>user.email</code> for git on my work computer. This is really just a post so when I forget how I did in the future I can google my own blog and be reminded...</p>
<p>I have always struggled with accidentally committing to an OSS project my work name/email or visa-versa, committing to a work git repo with my personal name/email.</p>
<p>For most, <code>user.name</code> shouldn't change, unless your company ties your <code>user.name</code> to something specific to the company like a username. (Contrast: <code>user.name = Jason Jarrett</code> and <code>user.name = jjarrett</code>).</p>
<p>When I clone projects I always clone them into a folder structure that looks like</p>
<pre><code>|____~/code
| |____personal/  &lt;--- <span class="hljs-keyword">this</span> <span class="hljs-keyword">is</span> where I would put some OSS projects <span class="hljs-literal">that</span> I may be working <span class="hljs-literal">on</span> <span class="hljs-keyword">or</span> contributing <span class="hljs-keyword">to</span>.
| |____work/      &lt;--- obviously work code goes <span class="hljs-keyword">in</span> here
</code></pre>
<p>Thanks to <a href="http://collectiveidea.com/blog/archives/2016/04/04/multiple-personalities-in-git/">this post</a> where I learned about <a href="http://direnv.net/">direnv</a> and followed the last option I basically used these steps...</p>
<h1>Setup</h1>
<ol>
<li>
<p>Install <code>direnv</code> - <code>brew install direnv</code> (What about Windows? see <a href="https://github.com/direnv/direnv/issues/124">this github issue</a> and help make it work)</p>
</li>
<li>
<p>Create <code>.envrc</code> file <strong>for each profile</strong> needing to be setup with the following content</p>
<pre><code>export GIT_AUTHOR_EMAIL=<span class="hljs-tag">&lt;<span class="hljs-title">your</span> <span class="hljs-attribute">email</span>&gt;</span>
export GIT_AUTHOR_NAME=<span class="hljs-tag">&lt;<span class="hljs-title">your</span> <span class="hljs-attribute">name</span>&gt;</span>
export GIT_COMMITTER_EMAIL=<span class="hljs-tag">&lt;<span class="hljs-title">your</span> <span class="hljs-attribute">email</span>&gt;</span>
export GIT_COMMITTER_NAME=<span class="hljs-tag">&lt;<span class="hljs-title">your</span> <span class="hljs-attribute">name</span>&gt;</span>
</code></pre>
</li>
<li>
<p>After installing and setting the <code>.envrc</code> files <a href="http://direnv.net/"><code>direnv</code></a> will prompt to use the env file which we accept by running <code>direnv allow</code>.</p>
</li>
</ol>
<p>Now I should have the following structure</p>
<pre><code>|<span class="hljs-string">____~/code
</span>|<span class="hljs-string"> </span>|<span class="hljs-string">____personal/
</span>|<span class="hljs-string">    </span>|<span class="hljs-string">____.envrc   &lt;-- env settings with personal git user/email
</span>|<span class="hljs-string"> </span>|<span class="hljs-string">____work/
</span>|<span class="hljs-string">    </span>|<span class="hljs-string">____.envrc   &lt;-- env settings with work git user/email

</span></code></pre>
<h1>What did this do?</h1>
<p>Each time we <code>cd</code> into either a <code>personal/</code> or <code>work/</code> folder <code>direnv</code> will setup our shell with environment variables contained in that folder's <code>.envrc</code> file. This will then allow Git which respects these env vars and now we don't have to think about committing the wrong name/email to the wrong Git repositories.</p>
<p>Happy Gitting!</p>
]]></content>
    </entry>
</feed>