<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Michael Kühnel // Front-End Developer // Kassel</title>
    <description>Michael Kühnel, Front-End Developer from Kassel, Germany – blogging about markup, CSS, JavaScript, tooling and related stuff. Sometimes in English and sometimes in German.
</description>
    <link>http://michael-kuehnel.de/</link>
    <atom:link href="http://michael-kuehnel.de/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Thu, 06 Nov 2025 15:17:59 +0000</pubDate>
    <lastBuildDate>Thu, 06 Nov 2025 15:17:59 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>Stencil and Storybook – How to generate argTypes from JSDoc comments</title>
        <description>&lt;p&gt;When using Stencil with Storybook, you’ll quickly notice that Controls don’t work out of the box. This guide shows you how to automatically generate proper argTypes from your JSDoc comments using the Custom Elements Manifest.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/assets/img/storybook-props-table.png&quot; alt=&quot;Screenshot of a Storybook props table with controls matching the props types. For example: Radio buttons for a size attribut showing the options &apos;s&apos;, &apos;m&apos; and &apos;l&apos;.&quot; /&gt;
  &lt;figcaption&gt;The final result: a proper table with controls matching the props types.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;

&lt;p&gt;Storybook for Web Components relies on the &lt;a href=&quot;https://github.com/webcomponents/custom-elements-manifest&quot;&gt;Custom Elements Manifest&lt;/a&gt; to generate the props/attributes table below your default story from your JSDoc blocks. Even when using correct TypeScript types and JSDoc comments, these don’t automatically translate into proper Storybook Controls without some additional setup.&lt;/p&gt;

&lt;p&gt;You’ll end up with “Set object” buttons instead of proper select, radio, or boolean controls to play with your components attributes in Storybook.&lt;/p&gt;

&lt;p&gt;Let’s tackle this problem step by step.&lt;/p&gt;

&lt;h2 id=&quot;1-generating-a-custom-elements-manifest&quot;&gt;1. Generating a Custom Elements Manifest&lt;/h2&gt;

&lt;p&gt;The Custom Elements Manifest is a JSON file containing metadata about your web components – their properties, attributes, events, and methods. Storybook uses this metadata to automatically generate documentation and controls.&lt;/p&gt;

&lt;p&gt;First, install the Custom Elements Manifest Analyzer:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install --save-dev @custom-elements-manifest/analyzer
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Create a &lt;code&gt;custom-elements-manifest.config.js&lt;/code&gt; in your project root:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;export default {
  globs: [&apos;src/components/**/*.tsx&apos;],
  outdir: &apos;.&apos;,
  exclude: [&apos;**/*.spec.tsx&apos;, &apos;**/*.e2e.tsx&apos;, &apos;**/*.stories.tsx&apos;],
  dev: false,
  litelement: false,
  catalyst: false,
  stencil: true,
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Add a script to your &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;scripts&quot;: {
    &quot;analyze&quot;: &quot;custom-elements-manifest analyze&quot;,
    &quot;prebuild&quot;: &quot;npm run analyze&quot;,
    &quot;build&quot;: &quot;stencil build&quot;,
    &quot;prestorybook&quot;: &quot;npm run build&quot;,
    &quot;storybook&quot;: &quot;storybook dev -p 6006&quot;,
    &quot;prebuild-storybook&quot;: &quot;npm run build&quot;,
    &quot;build-storybook&quot;: &quot;storybook build&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;prebuild&lt;/code&gt; script ensures the manifest is regenerated before each Stencil build. The &lt;code&gt;prestorybook&lt;/code&gt; and &lt;code&gt;prebuild-storybook&lt;/code&gt; scripts run the full build (which includes generating the manifest via &lt;code&gt;prebuild&lt;/code&gt;) to ensure both the components and the manifest are up-to-date before starting or building Storybook.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Add &lt;code&gt;custom-elements.json&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt; since it’s a generated file.&lt;/p&gt;

&lt;h2 id=&quot;2-enriching-the-manifest-with-type-information&quot;&gt;2. Enriching the Manifest with Type Information&lt;/h2&gt;

&lt;p&gt;Stencil sometimes omits type information for boolean props in the generated manifest. We need a plugin to fix this:&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;stencil-manifest-plugin.js&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;/**
 * Custom Elements Manifest Plugin for Stencil components
 * 
 * This plugin enriches the custom-elements.json generated by Stencil with
 * missing type information and removes internal implementation details.
 * 
 * Functions:
 * 1. Type Enrichment: Transfers type information from @Prop() members to their
 *    corresponding HTML attributes. This is necessary because Stencil sometimes
 *    omits type information in attributes for boolean props.
 * 
 * 2. Member Filtering: Removes internal @State() and other non-public members
 *    from the manifest, keeping only @Prop() declarations with corresponding
 *    HTML attributes.
 * 
 * Used by: Storybook for automatic Control generation
 */
export const stencilEnrichAttributeTypes = {
  name: &apos;stencil-enrich-attribute-types&apos;,
  moduleLinkPhase({ moduleDoc }) {
    moduleDoc?.declarations?.forEach(declaration =&amp;gt; {
      if (declaration.members &amp;amp;&amp;amp; declaration.attributes) {
        // Create a map from fieldName to member for type lookup
        const memberMap = new Map();
        declaration.members.forEach(member =&amp;gt; {
          if (member.name) {
            memberMap.set(member.name, member);
          }
        });

        // Add missing type information to attributes
        declaration.attributes.forEach(attr =&amp;gt; {
          if (attr.fieldName &amp;amp;&amp;amp; !attr.type) {
            const member = memberMap.get(attr.fieldName);
            if (member?.type) {
              attr.type = member.type;
            }
          }
        });
      }

      // Filter out @State() and other internal members
      if (declaration.members) {
        declaration.members = declaration.members.filter(member =&amp;gt; {
          // Keep only @Prop() members (those have an attribute)
          return member.kind === &apos;field&apos; &amp;amp;&amp;amp; member.attribute;
        });
      }
    });
  },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Update your &lt;code&gt;custom-elements-manifest.config.js&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { stencilEnrichAttributeTypes } from &apos;./stencil-manifest-plugin.js&apos;;

export default {
  globs: [&apos;src/components/**/*.tsx&apos;],
  outdir: &apos;.&apos;,
  exclude: [&apos;**/*.spec.tsx&apos;, &apos;**/*.e2e.tsx&apos;, &apos;**/*.stories.tsx&apos;],
  dev: false,
  litelement: false,
  catalyst: false,
  stencil: true,
  plugins: [stencilEnrichAttributeTypes],
};
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;3-configuring-storybook&quot;&gt;3. Configuring Storybook&lt;/h2&gt;

&lt;p&gt;Storybook’s &lt;code&gt;.storybook/preview.js&lt;/code&gt; file is the central configuration for customizing how stories are rendered and controlled. There are several ways to adapt preview rendering – using decorators, loaders, or enhancers. For our use case, we’ll use argTypesEnhancers, which allows us to programmatically generate argTypes based on the Custom Elements Manifest.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;.storybook/enhance-arg-types.js&lt;/code&gt; to handle the argTypes generation:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import customElements from &apos;../custom-elements.json&apos;;

/**
 * Enhances argTypes for Storybook based on Custom Elements Manifest
 * Automatically generates proper controls for union types, booleans, numbers, etc.
 */
export function enhanceArgTypes(context) {
  const { component } = context;
  if (!component) return {};

  const componentDef = customElements?.modules
    ?.flatMap((m) =&amp;gt; m.declarations || [])
    ?.find((d) =&amp;gt; d.tagName === component);

  if (!componentDef) return {};

  const argTypes = {};

  // Attributes/Props
  componentDef.attributes?.forEach((attr) =&amp;gt; {
    const name = attr.name;
    
    argTypes[name] = {
      description: attr.description,
      table: {
        defaultValue: { summary: attr.default?.replace(/&apos;/g, &apos;&apos;) },
        category: &apos;attributes&apos;,
      },
    };

    if (attr.type?.text) {
      const text = attr.type.text;
      
      // Handle union types like &apos;info&apos; | &apos;success&apos; | &apos;error&apos;
      if (text.includes(&apos;|&apos;)) {
        const options = text
          .split(&apos;|&apos;)
          .map(v =&amp;gt; v.trim().replace(/[&apos;&quot;]/g, &apos;&apos;));
        
        argTypes[name].control = {
          type: options.length &amp;lt;= 3 ? &apos;inline-radio&apos; : &apos;select&apos;,
        };
        argTypes[name].options = options;
      } else if (text === &apos;boolean&apos;) {
        argTypes[name].control = { type: &apos;boolean&apos; };
        argTypes[name].type = &apos;boolean&apos;;
      } else if (text === &apos;number&apos;) {
        argTypes[name].control = { type: &apos;number&apos; };
      } else {
        argTypes[name].control = { type: &apos;text&apos; };
      }
    }
  });

  // Events
  componentDef.events?.forEach((event) =&amp;gt; {
    argTypes[event.name] = {
      description: event.description,
      table: {
        category: &apos;events&apos;,
        type: { summary: event.type?.text || &apos;CustomEvent&apos; },
      },
      control: false,
    };
  });

  return argTypes;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now update your &lt;code&gt;.storybook/preview.js&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { setCustomElementsManifest } from &apos;@storybook/web-components&apos;;
import customElements from &apos;../custom-elements.json&apos;;
import { defineCustomElements } from &apos;../dist/loader&apos;;
import { enhanceArgTypes } from &apos;./enhance-arg-types.js&apos;;

setCustomElementsManifest(customElements);
defineCustomElements();

const preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
      hideNoControlsWarning: true,
    },
  },
  argTypesEnhancers: [enhanceArgTypes],
  tags: [&apos;autodocs&apos;]
};

export default preview;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;writing-your-stories&quot;&gt;Writing Your Stories&lt;/h2&gt;

&lt;p&gt;With the global enhancer in place, your stories become much simpler by ommiting the &lt;code&gt;argTypes&lt;/code&gt; and only providing the default &lt;code&gt;args&lt;/code&gt; values:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import type { Meta, StoryObj } from &apos;@storybook/web-components-vite&apos;;
import { html } from &apos;lit&apos;;

const meta: Meta = {
  title: &apos;Components/Alert&apos;,
  component: &apos;my-alert&apos;,
  tags: [&apos;autodocs&apos;],
};

export default meta;

export const Alert: StoryObj = {
  args: {
    variant: &apos;info&apos;,
    text: &apos;Here is the info text&apos;,
    &apos;has-close-button&apos;: true,
  },
  render: (args) =&amp;gt; html`
    &amp;lt;my-alert
      variant=${args.variant}
      ?has-close-button=${args[&apos;has-close-button&apos;]}
    &amp;gt;${args.text}&amp;lt;/my-alert&amp;gt;
  `,
};
&lt;/code&gt;&lt;/pre&gt;

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

&lt;ul&gt;
  &lt;li&gt;Use kebab-case for attribute names in args (&lt;code&gt;&apos;has-close-button&apos;&lt;/code&gt; not &lt;code&gt;hasCloseButton&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Use Lit’s boolean attribute syntax &lt;code&gt;?attribute-name&lt;/code&gt; for boolean props&lt;/li&gt;
  &lt;li&gt;Slots can be added as regular args and rendered as children&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;example-component&quot;&gt;Example Component&lt;/h2&gt;

&lt;p&gt;Here’s how to properly document your Stencil components:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { Component, Host, h, Prop } from &apos;@stencil/core&apos;;

/**
 * Component for an alert box.
 */
@Component({
  tag: &apos;my-alert&apos;,
  styleUrl: &apos;my-alert.scss&apos;,
  shadow: true,
})
export class MyAlert {
  /**
   * Variant of the alert.
   * @type {&apos;info&apos; | &apos;success&apos; | &apos;error&apos; | &apos;warning&apos;}
   * @default &apos;info&apos;
   */
  @Prop() variant: &apos;info&apos; | &apos;success&apos; | &apos;error&apos; | &apos;warning&apos; = &apos;info&apos;;

  /**
   * Whether the close button should be displayed.
   * @type boolean
   * @default true
   */
  @Prop() hasCloseButton = true;

  render() {
    return (
      &amp;lt;Host&amp;gt;
        &amp;lt;div class={`alert alert-${this.variant}`}&amp;gt;
          &amp;lt;slot /&amp;gt;
          {this.hasCloseButton &amp;amp;&amp;amp; (
            &amp;lt;button type=&quot;button&quot;&amp;gt;
              &amp;lt;i class=&quot;fa fa-close&quot; /&amp;gt;
            &amp;lt;/button&amp;gt;
          )}
        &amp;lt;/div&amp;gt;
      &amp;lt;/Host&amp;gt;
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The JSDoc comments are essential for proper documentation:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;@type&lt;/code&gt; defines the type (will be parsed for union types)&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;@default&lt;/code&gt; shows the default value in Storybook&lt;/li&gt;
  &lt;li&gt;Description appears in the Controls panel&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;result&quot;&gt;Result&lt;/h2&gt;

&lt;p&gt;With this setup, Storybook will automatically:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Generate radio buttons or select dropdowns for union types&lt;/li&gt;
  &lt;li&gt;Create boolean toggles for boolean props&lt;/li&gt;
  &lt;li&gt;Display text inputs for strings&lt;/li&gt;
  &lt;li&gt;Show number inputs for numbers&lt;/li&gt;
  &lt;li&gt;List events in the events category&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No manual &lt;code&gt;argTypes&lt;/code&gt; configuration needed in your stories!&lt;/p&gt;

&lt;h2 id=&quot;additional-resources&quot;&gt;Additional Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/webcomponents/custom-elements-manifest&quot;&gt;Custom Elements Manifest&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://storybook.js.org/docs/web-components/get-started/introduction&quot;&gt;Storybook Web Components&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stenciljs.com/docs/introduction&quot;&gt;Stencil Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 05 Nov 2025 11:00:00 +0000</pubDate>
        <link>http://michael-kuehnel.de/web%20components/2025/11/05/stencil-storybook-argtypes-from-jsdoc-comments.html</link>
        <guid isPermaLink="true">http://michael-kuehnel.de/web%20components/2025/11/05/stencil-storybook-argtypes-from-jsdoc-comments.html</guid>
        
        <category>Stencil,</category>
        
        <category>Storybook,</category>
        
        <category>Web</category>
        
        <category>Components,</category>
        
        <category>Custom</category>
        
        <category>Elements</category>
        
        <category>Manifest,</category>
        
        <category>JSDoc,</category>
        
        <category>argTypes,</category>
        
        <category>TypeScript</category>
        
        
        <category>Web Components</category>
        
      </item>
    
      <item>
        <title>How to flash ESP8266 (and ESP32) to use Espruino firmware on macOS</title>
        <description>&lt;p&gt;Espruino is a firmware with an integrated JavaScript interpreter for microcontrollers coming with it’s own IDE. So it’s possible to run JavaScript natively on the most affordable microcontrollers like the ESP8266. This Guide helps you to set things up to explore the possibilities of the Internet of Things using the language of the web.&lt;/p&gt;

&lt;h2 id=&quot;about-espruinos-javascript-abilities&quot;&gt;About Espruinos JavaScript abilities&lt;/h2&gt;

&lt;p&gt;Espruino sports a subset of ES6 features as shown in the &lt;a href=&quot;https://www.espruino.com/Features&quot;&gt;language feature&lt;/a&gt; list. You’ll find the comprehensive &lt;a href=&quot;https://www.espruino.com/Reference#software&quot;&gt;API documentation&lt;/a&gt; including built-in modules on the website as well.&lt;/p&gt;

&lt;p&gt;The module system is similiar to CommonJS but you won’t be able to use the npm eco system. Learn more about Espruinos &lt;a href=&quot;https://www.espruino.com/Modules&quot;&gt;modules&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;espruino-compatible-microcontrollers&quot;&gt;Espruino compatible microcontrollers&lt;/h2&gt;

&lt;p&gt;Espruino &lt;a href=&quot;https://shop.espruino.com/espruino-boards&quot;&gt;sells&lt;/a&gt; different own development boards with various hardware features that are specifically designed to work with this firmware. Fortunately, Espruino can also be used with other, much cheaper &lt;a href=&quot;https://www.espruino.com/Other+Boards&quot;&gt;boards&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I recommend using a development board (D1 Mini or NodeMCU) based on the ESP8266 or ESP32 depending on your needs. The main difference (beside the size and the price) is that the ESP32 comes with Bluetooth 4.2 and Bluetooth low energy in addition to the WI-FI capabilities of the ESP32. See &lt;a href=&quot;https://makeradvisor.com/esp32-vs-esp8266/&quot;&gt;this comparison&lt;/a&gt; to make your choice.&lt;/p&gt;

&lt;h2 id=&quot;install-macos-drivers&quot;&gt;Install macOS drivers&lt;/h2&gt;

&lt;p&gt;Download and install one of the following drivers to be able to successfully connect your development board via USB to your Mac:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/adrianmihalko/ch340g-ch34g-ch34x-mac-os-x-driver&quot;&gt;ESP8266&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers&quot;&gt;ESP32&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;load-and-enable-the-extensions&quot;&gt;Load and enable the extensions&lt;/h3&gt;

&lt;p&gt;Since macOS High Sierra you have to load and enable the drivers after the installation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Loading the ESP8266 driver in the Terminal:&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo kextload /Library/Extensions/usbserial.kext
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Loading the ESP32 driver in the Terminal:&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo kextload /Library/Extensions/SiLabsUSBDriver.kext
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&lt;br /&gt;
After loading the driver you have to approve the usage by clicking the »Allow« button in the »Security &amp;amp; Privacy« system preferences panel.&lt;/p&gt;

&lt;h2 id=&quot;install-esptool&quot;&gt;Install esptool&lt;/h2&gt;

&lt;p&gt;You need a command line tool called »esptool« to be able to flash your ESP based development board. You can get it via HomeBrew:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;brew install esptool
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;flashing&quot;&gt;Flashing&lt;/h2&gt;

&lt;p&gt;Connect your ESP via USB to your Mac.&lt;/p&gt;

&lt;h3 id=&quot;check-connectivity&quot;&gt;Check connectivity&lt;/h3&gt;

&lt;p&gt;Enter the following to figure out if you verything is set up properly:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;esptool.py flash_id
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If the driver is correctly installed and activated your Terminal should respond with something like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-markup&quot;&gt;esptool.py v2.6
Found 5 serial ports
Serial port /dev/cu.wchusbserial1440
Connecting....
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
MAC: 84:f3:eb:ed:6d:54
Uploading stub...
Running stub...
Stub running...
Manufacturer: 68
Device: 4016
Detected flash size: 4MB
Hard resetting via RTS pin...
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&quot;port&quot;&gt;Port&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;Serial port /dev/cu.wchusbserial1440&lt;/code&gt; tells us which port to use for flashing the ESP and transfering code to it later..&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: Your port may differ.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;download-firmware&quot;&gt;Download firmware&lt;/h3&gt;

&lt;p&gt;Visit &lt;a href=&quot;http://www.espruino.com/Download&quot;&gt;http://www.espruino.com/Download&lt;/a&gt; to get the latest Espruino release:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Choose your board (ESP32 respectively ESP8266)&lt;/li&gt;
  &lt;li&gt;Click the following link
    &lt;ul&gt;
      &lt;li&gt;for ESP8266:
        &lt;blockquote&gt;
          &lt;p&gt;Release: espruino_[latest-version]_esp8266_4mb/ (Directory)&lt;/p&gt;
        &lt;/blockquote&gt;
      &lt;/li&gt;
      &lt;li&gt;for ESP32:
        &lt;blockquote&gt;
          &lt;p&gt;Release: espruino_[latest-version]_esp32/ (Directory)&lt;/p&gt;
        &lt;/blockquote&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Create a directory and download all files&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;erase-your-board&quot;&gt;Erase your board&lt;/h3&gt;

&lt;p&gt;Enter the following to erase the flash of your board:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;esptool.py --port /dev/&amp;lt;port&amp;gt; erase_flash
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Note: Replace &lt;code&gt;&amp;lt;port&amp;gt;&lt;/code&gt; with your port.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;write-firmware&quot;&gt;Write firmware&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Replace &lt;code&gt;&amp;lt;path/to/firmware&amp;gt;&lt;/code&gt; with the directory directory containing the downloaded firmware files.&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Replace &lt;code&gt;&amp;lt;port&amp;gt;&lt;/code&gt; with your port.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;esp8266&quot;&gt;ESP8266&lt;/h4&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ cd &amp;lt;path/to/firmware&amp;gt;
$ esptool.py                                    \
    --port /dev/&amp;lt;port&amp;gt;             \
    --baud 115200                               \
    write_flash                                 \
    --flash_freq 80m                            \
    --flash_mode qio                            \
    --flash_size 32m                            \
    0x0000 boot_v1.6.bin                        \
    0x1000 espruino_esp8266_user1.bin           \
    0x3FC000 esp_init_data_default.bin          \
    0x3FE000 blank.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&quot;esp32&quot;&gt;ESP32&lt;/h4&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ cd &amp;lt;path/to/firmware&amp;gt;
$ esptool.py                                    \
    --chip esp32                                \
    --port /dev/&amp;lt;port&amp;gt;               \
    --baud 921600                               \
    --after hard_reset write_flash              \
    -z                                          \
    --flash_mode dio                            \
    --flash_freq 40m                            \
    --flash_size detect                         \
    0x1000 bootloader.bin                       \
    0x8000 partitions_espruino.bin              \
    0x10000 espruino_esp32.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;testing-aka-hello-world&quot;&gt;Testing aka Hello World&lt;/h2&gt;

&lt;p&gt;Horray, We should now be able to run JavaScript on the board 🎉&lt;/p&gt;

&lt;p&gt;Let’s check if everythings works like expected:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Install the &lt;a href=&quot;https://www.espruino.com/Web+IDE&quot;&gt;Espruino Web IDE&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Set the correct connection speed
    &lt;ol&gt;
      &lt;li&gt;ESP8266: Settings → Communications → Baud Rate → 115200&lt;/li&gt;
      &lt;li&gt;ESP32: Settings → Communications → Baud Rate → 921600&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;Hit the »connect« button in the upper left corner&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Enter the following code to interact with the built in LED:&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt; // ESP8266
 const pin = 2;
  
 // ESP32
 //const pin = 8;
  
 let on = 0;
 digitalWrite(pin, on);
 setInterval(() =&amp;gt; {
   on = on === 0 ? 1 : 0;
   digitalWrite(pin, on);
 }, 100);
&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;Hit the »Send to Espruino« button to transfer the code to your board&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Tip: See Espruinos &lt;a href=&quot;https://www.espruino.com/Quick+Start+Code&quot;&gt;Quick Start&lt;/a&gt; for writing code Espruino IDE to learn more.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;espruino-cli-as-alternative-to-using-espruino-ide&quot;&gt;Espruino CLI as alternative to using Espruino IDE&lt;/h2&gt;

&lt;p&gt;The Espruino CLI can be used to send the code your are writing with any code editor to your board.&lt;/p&gt;

&lt;p&gt;This way you can use the features of the IDE/editor you are used to when writing JavaScript.&lt;/p&gt;

&lt;h2 id=&quot;install&quot;&gt;Install&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install espruino -g
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Enter &lt;code&gt;espruino -h&lt;/code&gt; to see all available options.&lt;/p&gt;

&lt;h2 id=&quot;list-all-available-devices-and-exit&quot;&gt;List all available devices and exit&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;espruino --list
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;useful-snippets&quot;&gt;Useful snippets&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt;
&lt;em&gt;Replace &lt;code&gt;/dev/&amp;lt;port&amp;gt;&lt;/code&gt; with your port and the baud rate from &lt;code&gt;115200&lt;/code&gt; to &lt;code&gt;921600&lt;/code&gt; when using an ESP32.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;reset-the-code-on-your-board&quot;&gt;Reset the code on your board&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;espruino -p /dev/&amp;lt;port&amp;gt; -b 115200 -e &apos;reset(); digitalWrite(2, 1); save();
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;push-code-to-board&quot;&gt;Push code to board&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;espruino -p /dev/&amp;lt;port&amp;gt; -b 115200 filename.js
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;push-code-to-board-and-save&quot;&gt;Push code to board and save&lt;/h3&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;espruino -p /dev/tty.wchusbserial14110 -b 115200 -e &apos;save()&apos; filename.js
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;additional-links&quot;&gt;Additional links&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.espruino.com/EspruinoESP8266&quot;&gt;https://www.espruino.com/EspruinoESP8266&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.espruino.com/ESP32&quot;&gt;https://www.espruino.com/ESP32&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.espruino.com/Tutorials&quot;&gt;https://www.espruino.com/Tutorials&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 16 Jul 2019 23:34:16 +0000</pubDate>
        <link>http://michael-kuehnel.de/iot/2019/07/16/how-to-flash-esp8266-and-esp32-to-use-espruino-firmware-on-mac-os.html</link>
        <guid isPermaLink="true">http://michael-kuehnel.de/iot/2019/07/16/how-to-flash-esp8266-and-esp32-to-use-espruino-firmware-on-mac-os.html</guid>
        
        <category>IoT,</category>
        
        <category>Internet</category>
        
        <category>of</category>
        
        <category>Things,</category>
        
        <category>Espruino,</category>
        
        <category>ESP8266,</category>
        
        <category>ESP32,</category>
        
        <category>D1</category>
        
        <category>Mini,</category>
        
        <category>NodeMCU,</category>
        
        <category>JavaScript,</category>
        
        <category>Microcontrollers,</category>
        
        <category>macOS</category>
        
        
        <category>IoT</category>
        
      </item>
    
      <item>
        <title>Helpers and tips for npm run scripts</title>
        <description>&lt;p&gt;The purpose of this blog post is not to introduce using npm as a build tool. There are lots of good articles about the »where« and »why«. I would like to present some hidden gems to potentially improve your setup instead.&lt;/p&gt;

&lt;p&gt;I’d like to point to &lt;a href=&quot;https://css-tricks.com/why-npm-scripts/&quot;&gt;Why npm Scripts?&lt;/a&gt; if you want to read an introduction to the benefits of using CLI tools via npm scripts in favor of a task runner like Gulp and their plugin eco system.&lt;/p&gt;

&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;You can easily &lt;a href=&quot;https://docs.npmjs.com/cli/run-script&quot;&gt;run scripts&lt;/a&gt; using npm by adding them to the &lt;code&gt;&quot;scripts&quot;&lt;/code&gt; field in package.json and run them with &lt;code&gt;npm run &amp;lt;script-name&amp;gt;&lt;/code&gt;. Run &lt;code&gt;npm run&lt;/code&gt; to see available scripts. Binaries of locally install packages are made available in the &lt;code&gt;PATH&lt;/code&gt;, so you can run them by name instead of pointing to &lt;code&gt;node_modules/.bin/name&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
	&quot;name&quot;: &quot;my-package&quot;,
	&quot;scripts&quot;: {
		&quot;lint&quot;: &quot;eslint .&quot;
	},
	&quot;devDependencies&quot;: {
		&quot;eslint&quot;: &quot;^4.19.0&quot;
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ npm run lint
&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;lifecycle-scripts&quot;&gt;Lifecycle scripts&lt;/h2&gt;

&lt;p&gt;npm comes with predefined &lt;a href=&quot;https://docs.npmjs.com/misc/scripts&quot;&gt;lifecyle scripts&lt;/a&gt; which are excuted under specific conditions when they are defined in your package.json.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;name&quot;: &quot;my-package&quot;,
  &quot;scripts&quot;: {
    &quot;prepublishOnly&quot;: &quot;nsp check&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;nsp&quot;: &quot;^3.2.1&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will be executed automatically before your npm package is published to the registry via &lt;code&gt;npm publish&lt;/code&gt; to check for known vulnerabilties in your dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: &lt;em&gt;prepublishOnly&lt;/em&gt; is available since npm v4.0.0. See &lt;a href=&quot;https://docs.npmjs.com/misc/scripts#deprecation-note&quot;&gt;npm docs&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;npm-start-and-npm-test&quot;&gt;»npm start« and »npm test«&lt;/h3&gt;

&lt;p&gt;These are also lifecycle scripts (but aren’t executed automatically).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;name&quot;: &quot;my-package&quot;,
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;node server.js&quot;,
    &quot;test&quot;: &quot;jest&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;jest-cli&quot;: &quot;^22.4.2&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Therefore they can be executed simply with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ npm test
$ npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;pre-and-post-scripts&quot;&gt;»pre« and »post« scripts&lt;/h3&gt;

&lt;p&gt;»pre« and »post« scripts are special lifecycle scripts which can be used to run scripts automatically in sequence.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;name&quot;: &quot;my-package&quot;,
  &quot;scripts&quot;: {
    &quot;pretest&quot;: &quot;eslint .&quot;,
    &quot;test&quot;: &quot;jest&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;eslint&quot;: &quot;^4.19.0&quot;,
    &quot;jest-cli&quot;: &quot;^22.4.2&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ npm test
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will lint your files before running your tests. The tests will not run if linting fails, or more generally: the following script won’t be executed if one of the scripts running in sequence exits with an exit code other than 0.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: »pre« and »post« scripts can also be used for your custom npm scripts. So &lt;code&gt;npm run foo&lt;/code&gt; will also run &lt;code&gt;prefoo&lt;/code&gt; and &lt;code&gt;postfoo&lt;/code&gt; if defined.&lt;/strong&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;options-for-npm-scripts&quot;&gt;Options for npm scripts&lt;/h2&gt;

&lt;h4 id=&quot;passing-options-to-used-commands&quot;&gt;Passing options to used commands&lt;/h4&gt;

&lt;p&gt;You can pass options to the command you are using in your npm script by adding &lt;code&gt;-- --flag&lt;/code&gt; like in the example below.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;name&quot;: &quot;my-package&quot;,
  &quot;scripts&quot;: {
    &quot;lint&quot;: &quot;xo&quot;,
    &quot;lint:fix&quot;: &quot;npm run lint -- --fix&quot;,
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Adding the &lt;code&gt;-- --fix &lt;/code&gt; option is like executing &lt;code&gt;xo --fix&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;silent-option&quot;&gt;Silent option&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;npm run&lt;/code&gt; has a &lt;code&gt;--silent&lt;/code&gt; option which is especially useful when combining npm scripts in npm scripts.&lt;/p&gt;

&lt;p&gt;Imagine you have a setup for linting your JavaScript files like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;name&quot;: &quot;my-package&quot;,
  &quot;scripts&quot;: {
    &quot;lint&quot;: &quot;xo&quot;,
    &quot;lint:fix&quot;: &quot;npm run lint --silent -- --fix&quot;,
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using the –silent option reduces the output in the Terminal. See this &lt;a href=&quot;https://twitter.com/mkuehnel/status/957965749473210369&quot;&gt;comparison&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;helper-packages&quot;&gt;Helper packages&lt;/h2&gt;

&lt;h3 id=&quot;watch-tasks&quot;&gt;Watch tasks&lt;/h3&gt;

&lt;p&gt;There are several packages which enable running scripts when files changed. Personally, &lt;a href=&quot;https://github.com/Qard/onchange&quot;&gt;onchange&lt;/a&gt; offers the best combination of ease of use and flexibility.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
	&quot;name&quot;: &quot;my-package&quot;,
	&quot;scripts&quot;: {
		&quot;lint&quot;: &quot;eslint src&quot;,
    &quot;lint:watch&quot;: &quot;onchange \&quot;src/**/*.js\&quot; -- npm run lint --silent&quot;
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So &lt;code&gt;npm run lint:watch&lt;/code&gt; will watch for changes in the file system and will automatically run eslint when a file changes.&lt;/p&gt;

&lt;h3 id=&quot;get-notified-in-error-cases&quot;&gt;Get notified in error cases&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/micromata/cli-error-notifier&quot;&gt;cli-error-notifier&lt;/a&gt; sends native desktop notifications when npm scripts fail.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;scripts&quot;: {
    &quot;lint&quot;: &quot;onerror \&quot;eslint src\&quot;&quot;,
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is especially useful for watching files while developing in conjunction with &lt;code&gt;onchange&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;scripts&quot;: {
    &quot;lint&quot;: &quot;eslint src&quot;,
    &quot;lint:fix&quot;: &quot;npm run lint --silent -- --fix&quot;,
    &quot;lint:watch&quot;: &quot;onchange \&quot;src/**/*.js\&quot; -- onerror \&quot;npm run lint --silent\&quot;&quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;run-multiple-scripts-in-parallel-or-serial&quot;&gt;Run multiple scripts in parallel or serial&lt;/h3&gt;

&lt;p&gt;Using &lt;a href=&quot;https://github.com/mysticatea/npm-run-all&quot;&gt;npm-run-all&lt;/a&gt; offers the following advantages:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;can increase readability of the scripts section in your package.json via glob-like patterns&lt;br /&gt;
Before:&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;npm run clean &amp;amp;&amp;amp; npm run build:css &amp;amp;&amp;amp; npm run build:js &amp;amp;&amp;amp; npm run build:html
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;After:&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;npm-run-all clean build:*
&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;compared to using &lt;code&gt;npm run foo &amp;amp; npm run bar&lt;/code&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;running scripts in parallel works on Windows&lt;/li&gt;
      &lt;li&gt;multiple scripts which are listening to file changes can run parallel&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;npm-run-all clean --parallel webpack:server lint:watch&quot;,
    &quot;build&quot;: &quot;npm-run-all security test clean webpack&quot;,
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;remembering-npm-run-scripts&quot;&gt;Remembering npm run scripts&lt;/h3&gt;

&lt;p&gt;Depending on the amount of tasks it might be hard to remember each and every task name. A faster alternative to use &lt;code&gt;npm run&lt;/code&gt; to list all available tasks is to use an awesome little helper tool called &lt;a href=&quot;https://github.com/ruyadorno/ntl&quot;&gt;ntl&lt;/a&gt; to show an interactive list of task to choose from 💥&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/ntl-screenshot.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;beyond-npm-scripts&quot;&gt;Beyond npm scripts&lt;/h2&gt;

&lt;h3 id=&quot;wrap-your-npm-scripts-setup-to-improve-maintainibility-and-user-experience&quot;&gt;Wrap your npm scripts setup to improve maintainibility and user experience&lt;/h3&gt;

&lt;p&gt;There are two things which might have a downside when your setup becomes more and more complex:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Not being able to describe your tasks to your users.
    &lt;ul&gt;
      &lt;li&gt;You might want to upvote &lt;a href=&quot;https://github.com/npm/npm/issues/18515&quot;&gt;this issue&lt;/a&gt; on the npm issues tracker to fix this.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The lack of using comments in package.json.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As workaround for both you can use a tool like &lt;a href=&quot;https://github.com/kentcdodds/nps&quot;&gt;nps&lt;/a&gt; which claims to have »all the benefits of npm scripts without the cost of a bloated package.json and limits of json«.&lt;/p&gt;

&lt;h4 id=&quot;the-solution-of-nps&quot;&gt;The solution of nps&lt;/h4&gt;

&lt;p&gt;It allows you to move your scripts to a &lt;code&gt;package-scripts.js&lt;/code&gt; file. Because this file is a JavaScript file, you can do a lot more with your project scripts.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const npsUtils = require(&apos;nps-utils&apos;) // not required, but handy!

module.exports = {
  scripts: {
    default: &apos;node index.js&apos;,
    lint: &apos;eslint .&apos;,
    test: {
      default: &apos;jest&apos;,
      watch: {
        script: &apos;jest --watch&apos;,
        description: &apos;run in the amazingly intelligent Jest watch mode&apos;
      }
    },
    build: {
      default: &apos;webpack&apos;,
      prod: &apos;webpack -p&apos;,
    },
    // learn more about npsUtils here: https://npm.im/nps-utils
    validate: npsUtils.concurrent.nps(&apos;lint&apos;, &apos;test&apos;, &apos;build&apos;),
  },
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;using-npx-with-locally-installed-dependencies-instead-of-npm-run-scripts&quot;&gt;Using npx with locally installed dependencies instead of npm run scripts&lt;/h3&gt;

&lt;p&gt;npm &lt;a href=&quot;https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b&quot;&gt;comes bundled&lt;/a&gt; with &lt;code&gt;npx&lt;/code&gt; (since v5.2.0) — a tool to execute package binaries which is great to use packages globally without the need to install them globally.&lt;/p&gt;

&lt;p&gt;But it’s also pretty useful for locally installed dependencies in your project.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Each command called with &lt;code&gt;npx&lt;/code&gt; is executed either from the local &lt;code&gt;node_modules/.bin&lt;/code&gt; directory, or from a central cache, installing any packages needed in order to run a command.&lt;/em&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
	&quot;name&quot;: &quot;my-package&quot;,
	&quot;scripts&quot;: {
		&quot;lint&quot;: &quot;xo&quot;
	},
	&quot;devDependencies&quot;: {
		&quot;xo&quot;: &quot;^0.20.0&quot;
	}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx xo --fix
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This executes the locally installed version of XO from &lt;code&gt;node_modules/.bin&lt;/code&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;That’s it for now. Please share other features, tips and tools I might have missed.&lt;/p&gt;
</description>
        <pubDate>Thu, 22 Mar 2018 23:30:00 +0000</pubDate>
        <link>http://michael-kuehnel.de/tooling/2018/03/22/helpers-and-tips-for-npm-run-scripts.html</link>
        <guid isPermaLink="true">http://michael-kuehnel.de/tooling/2018/03/22/helpers-and-tips-for-npm-run-scripts.html</guid>
        
        <category>Tooling,</category>
        
        <category>npm</category>
        
        <category>scripts,</category>
        
        <category>helpers,</category>
        
        <category>cli,</category>
        
        <category>tips,</category>
        
        <category>watch</category>
        
        
        <category>Tooling</category>
        
      </item>
    
      <item>
        <title>JSConf Budapest 2017 – A personal recap</title>
        <description>&lt;div class=&quot;float-container&quot;&gt;
    &lt;figure class=&quot;float-left&quot;&gt;
      &lt;img src=&quot;/assets/img/jsconfbp2017/family-photo.jpg&quot; alt=&quot;&quot; /&gt;
      &lt;figcaption&gt;Picture by &lt;a href=&quot;https://twitter.com/verpixelt&quot;&gt;Kevin Lorenz&lt;/a&gt;&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;div&gt;
        &lt;p&gt;
          It was my first time attending JSConf Budapest. In this recap I’ll summarize and highlight a few talks and try to convey the overall experience. TL;DR: It was a blast. Thanks to everyone involved :sparkling_heart:
        &lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&quot;general-remarks&quot;&gt;General remarks&lt;/h2&gt;

&lt;p&gt;JSConf Budapest is – besides JSConf EU (The first JSConf in europe) and JSConf Belgium – another JSConf happening at the european continent which actually took place for the third time and therefore already has a tradition to one’s name.&lt;/p&gt;

&lt;p&gt;For those who don’t know the concept of the whole JSConf thing I’d like to proceed with a short explanation.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://jsconf.com&quot;&gt;JSConfs&lt;/a&gt; happening around the globe are all community driven by heart. From the local community for the world-wide community. So there isn’t something like a huge common organizer behind all that conferences. But they do have something in common: All local organizers are focusing on the community aspect instead of being only tech driven. This is achieved by offering many possibilities for social interactions from lounges through open discussion panels to interactive games during evening events. All of that considering a code of conduct which is not only written somewhere on the conferences website, but also will be lived and enforced.&lt;/p&gt;

&lt;p&gt;Another important fact is that the organizers set a high value on diversity concerning the speakers as well as the attendees. They offer diversity support tickets for example. The additional charge is used to give members of underrepresented groups the possibility to attend the conference.&lt;/p&gt;

&lt;p&gt;The 2017 edition was the first JSConf Budapest for me after visiting JSConf EU in Berlin a while ago. I was very thrilled about Budapest accordingly.&lt;/p&gt;

&lt;h2 id=&quot;the-location&quot;&gt;The location&lt;/h2&gt;

&lt;div class=&quot;float-container&quot;&gt;
    &lt;figure class=&quot;float-left&quot;&gt;
      &lt;img src=&quot;/assets/img/jsconfbp2017/location.jpg&quot; alt=&quot;&quot; /&gt;
      &lt;figcaption&gt;Picture by &lt;a href=&quot;https://twitter.com/stefanjudis‬ &quot;&gt;Stefan Judis&lt;/a&gt;&lt;/figcaption&gt;
    &lt;/figure&gt;
    &lt;div&gt;
        &lt;p&gt;
          The event location was a historic cinema in the heart of the jewish quarter in the center of the city. A monumental location. The only thing I kinda missed were more places to chill. 
        &lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&quot;the-schedule&quot;&gt;The schedule&lt;/h2&gt;

&lt;p&gt;It was a two day, single track conference. So there was no need to be afraid of choosing the wrong track and miss a talk :smirk:&lt;/p&gt;

&lt;p&gt;The mixture of talks really was to my taste. The technical ones were predominating and there were very interesting talks which aren’t focused to technical details but enlightened human parts of our work life.&lt;/p&gt;

&lt;h3 id=&quot;personal-highlights-of-the-non-technical-talks&quot;&gt;Personal highlights of the non-technical talks&lt;/h3&gt;

&lt;p&gt;I’d like summarize and highlight the following three talks.&lt;/p&gt;

&lt;h4 id=&quot;bodil-stokke--you-have-nothing-to-lose-but-your-chains&quot;&gt;&lt;a href=&quot;https://twitter.com/bodil&quot;&gt;Bodil Stokke&lt;/a&gt; – You Have Nothing to Lose but Your Chains&lt;/h4&gt;

&lt;p&gt;The topic of this &lt;a href=&quot;https://bodil.lol/join-us-now/#0&quot;&gt;talk&lt;/a&gt; was Open Source Software. From their beginnings, through licenses to todays relevance. Whether you interpret Open Source and the Free Software movement as socialism, pragmatism or art: The idea itself and spreading is as important as it ever was. Then it has the ability to empower us. Making source code available to the general public doesn’t only mean that we can take influence, can fix and can improve software. It builds communities of developers and user which weren’t imaginable. First and foremost it enables us to learn.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/assets/img/jsconfbp2017/oss.jpg&quot; alt=&quot;&quot; /&gt;
  &lt;figcaption&gt;Picture by &lt;a href=&quot;https://twitter.com/mkuehnel&quot;&gt;myself&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 id=&quot;vaidehi-joshi--goldilocks-and-the-three-code-reviews&quot;&gt;&lt;a href=&quot;https://twitter.com/vaidehijoshi&quot;&gt;Vaidehi Joshi&lt;/a&gt; – Goldilocks and the three Code Reviews&lt;/h4&gt;

&lt;p&gt;This &lt;a href=&quot;http://slides.com/vaidehijoshi/better-code-reviews#/&quot;&gt;talk&lt;/a&gt; illustrated problems we have with code reviews wrapped in an entertaining story. Including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;tons of comments, little conversation&lt;/li&gt;
  &lt;li&gt;focusing on style / syntax&lt;/li&gt;
  &lt;li&gt;ego over empathy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plus it showed concrete opportunities for action to fix these problems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;review everyone: push for a culture that values vulnerability&lt;/li&gt;
  &lt;li&gt;develop empathy: call out the good stuff, too!&lt;/li&gt;
  &lt;li&gt;iterate: only iteration can improve the process&lt;/li&gt;
  &lt;li&gt;start the conversation&lt;/li&gt;
&lt;/ul&gt;

&lt;figure&gt;
  &lt;img src=&quot;/assets/img/jsconfbp2017/reviews.jpg&quot; alt=&quot;&quot; /&gt;
  &lt;figcaption&gt;Picture by &lt;a href=&quot;https://twitter.com/mkuehnel&quot;&gt;myself&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 id=&quot;madeleine-neumann--impostor-syndrome---am-i-suffering-enough-to-talk-about-it&quot;&gt;&lt;a href=&quot;https://twitter.com/maggysche&quot;&gt;Madeleine Neumann&lt;/a&gt; – Impostor syndrome - am I suffering enough to talk about it?&lt;/h4&gt;

&lt;p&gt;in this important psychological talk Madeleine told her personal story of career development in which the &lt;a href=&quot;https://medium.com/@Maggysche/impostor-syndrome-am-i-suffering-enough-to-write-about-it-5de8074f2c60&quot;&gt;Impostor Syndrome&lt;/a&gt; acts a part.
My main take away from the talk was that everyone has moments of suffering from self-doubts from time to time. Lastly Madeleine gave very useful tips about how to get out of the impostor zone. See &lt;a href=&quot;https://www.slideshare.net/MadeleineNeumann/jsconf-budapest-impostor-syndrome-am-i-suffering-enough-to-talk-about-it&quot;&gt;slides&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;personal-highlights-of-the-technical-talks&quot;&gt;Personal highlights of the technical talks&lt;/h3&gt;

&lt;p&gt;The following talks impressed me the most from the technical standpoint.&lt;/p&gt;

&lt;h4 id=&quot;stefan-judis--watch-your-back-browser-youre-being-observed&quot;&gt;&lt;a href=&quot;https://twitter.com/stefanjudis&quot;&gt;Stefan Judis&lt;/a&gt; – Watch your back, Browser! You’re being observed&lt;/h4&gt;

&lt;p&gt;A &lt;a href=&quot;https://speakerdeck.com/stefanjudis/watch-your-back-browser-youre-being-observed&quot;&gt;roundtrip&lt;/a&gt; across modern JavaScript web APIs which turns the way to gather information upside down. The concept of communications of older APIs mostly was based on a pull principle. Broadly speaking, you had to ask for information your are interested in. It seems that this has changed to an push principle with modern APIs.&lt;/p&gt;

&lt;p&gt;Shortly explained using the example of the pretty new &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API&quot;&gt;Intersection Observer API&lt;/a&gt;: This API offers the possibility to listen if a DOM node gets in the visible viewport and to asynchronously get notified in case this happens.&lt;/p&gt;

&lt;p&gt;The most prominent use cases are probably lazy loading images and implement infinite scrolling as an alternative to a classical pagination. We were of course able to implement these things before, but less performant and elegantly.&lt;/p&gt;

&lt;h4 id=&quot;jonathan-martin--async-patterns-to-scale-your-multicore-javascript--elegantly&quot;&gt;&lt;a href=&quot;https://twitter.com/nybblr&quot;&gt;Jonathan Martin&lt;/a&gt; – Async patterns to scale your multicore JavaScript … elegantly.&lt;/h4&gt;

&lt;p&gt;An excellent &lt;a href=&quot;https://speakerdeck.com/nybblr/async-patterns-to-scale-your-multicore-javascript-dot-dot-dot-elegantly&quot;&gt;talk&lt;/a&gt; about patterns to grasp the challenges when it comes to handle concurrency with sequential dependencies via JavaScript. Since the JavaScript interpreter in the browser and in Node is a single thread classical multithreading approaches don’t fit in here. But JavaScript and the underlying architecture based on the event loop, the call stack and the callback queue is a perfect match for concurrent programming.&lt;/p&gt;

&lt;p&gt;Jonathan came with recipes based on »Async IIFEs«, »Web Worker clusters« und »SharedArrayBuffers« to solve the concurrency challenges elegantly.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/assets/img/jsconfbp2017/concurrency.jpg&quot; alt=&quot;&quot; /&gt;
  &lt;figcaption&gt;Picture by &lt;a href=&quot;https://twitter.com/mkuehnel&quot;&gt;myself&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 id=&quot;eirik-vullum--javascript-metaprogramming---es6-proxy-use-and-abuse&quot;&gt;&lt;a href=&quot;https://twitter.com/eiriklv&quot;&gt;Eirik Vullum&lt;/a&gt; – JavaScript Metaprogramming - ES6 Proxy Use and Abuse&lt;/h4&gt;

&lt;p&gt;An interesting talk providing real world use cases for one of the few non-polyfillable / non-transpilable ES6 features which you can use in in the latest browsers and Node.js versions.&lt;/p&gt;

&lt;p&gt;A short explanation of proxies: JavaScript Proxies enables you to modify and extend fundamental language features (e.g. property lookup, assignment, enumeration, function invocation, etc).&lt;/p&gt;

&lt;p&gt;Beside quite useful mini examples like auto-logging of object keys when accessing object properties I really was impressed by an Oprn Source project from Eirik: &lt;a href=&quot;https://github.com/eiriklv/json-populate&quot;&gt;JSON-populate&lt;/a&gt;, which simplifies accessing JSON properties with circular dependencies by reference.&lt;/p&gt;

&lt;h3 id=&quot;parties-tada&quot;&gt;Parties :tada:&lt;/h3&gt;

&lt;p&gt;A very special highlight was the party after the first day of the conference. Mainly because &lt;a href=&quot;http://livejs.network/&quot;&gt;{Live : JS}&lt;/a&gt; had a truly amazing live gig. They performed music running on two Gameboy Advance and did bedazzling live visuals exclusively based on web technologies. Mad props to Ruth, Tim, Sam und Martin. These folks truly rocked the party.&lt;/p&gt;

&lt;h2 id=&quot;bottom-line&quot;&gt;Bottom line&lt;/h2&gt;

&lt;p&gt;Beside the talks (and the party) I especially was delighted by the social aspects of this conference attendance. It was a pleasure to see friends who I only have the chance to meet them once a year (beside hanging out with them online), as well as meeting new people who I knew before from Twitter only.&lt;/p&gt;

&lt;p&gt;Thanks to all the people for the nice conversations and your openness :sparkling_heart: Thanks to the folks for organizing JSConf Budapest :sparkling_heart: And thanks to my employer &lt;a href=&quot;https://www.micromata.de/&quot;&gt;Micromata&lt;/a&gt; for making it possible to attend JSConf Budapest :sparkling_heart:&lt;/p&gt;
</description>
        <pubDate>Tue, 14 Nov 2017 22:00:00 +0000</pubDate>
        <link>http://michael-kuehnel.de/conferences/2017/11/14/jsconf-budapest-2017.html</link>
        <guid isPermaLink="true">http://michael-kuehnel.de/conferences/2017/11/14/jsconf-budapest-2017.html</guid>
        
        <category>Conferences,</category>
        
        <category>JSconf</category>
        
        <category>Budapest</category>
        
        
        <category>conferences</category>
        
      </item>
    
      <item>
        <title>Quick Tip: Using Lodash per method packages with Angular (2 and above)</title>
        <description>&lt;h1 id=&quot;problems-with-using-lodash-per-method-packages&quot;&gt;Problems with using Lodash per method packages&lt;/h1&gt;

&lt;p&gt;I didn’t get how to import per method packages and how to include the types in my project.&lt;/p&gt;

&lt;p&gt;Therefore I encountered one or another of the following error Messages:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ERROR in /path/to/project/src/app/my.component.ts (3,10): Module &apos;&quot;/path/to/project/node_modules/@types/lodash/index&quot;&apos; has no exported member &apos;lodash&apos;.
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ERROR in /path/to/project/src/app/my.component.ts (3,22): Module &apos;&quot;/path/to/project/node_modules/@types/lodash.drop/index&quot;&apos; resolves to a non-module entity and cannot be imported using this construct.
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ERROR in /path/to/project/src/app/my.component.ts (71,24): Cannot find name &apos;dropRight&apos;.
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ERROR in Cannot read property &apos;getLineAndCharacterOfPosition&apos; of undefined
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It’ actually pretty much straight forward to fix these errors like described below.&lt;/p&gt;

&lt;h2 id=&quot;installing-lodash-per-method-packages&quot;&gt;Installing Lodash per method packages&lt;/h2&gt;

&lt;p&gt;In addition to the Lodash packages you have to install the type definitions:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install --save lodash.drop
npm install --save @types/lodash.drop

npm install --save lodash.dropright
npm install --save @types/lodash.dropright
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;add-type-definitions-to-your-project&quot;&gt;Add type definitions to your project&lt;/h2&gt;

&lt;p&gt;Add just the one and only item to the &lt;code&gt;types&lt;/code&gt; array in &lt;code&gt;src/tsconfig.app.json&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;{
  &quot;compilerOptions&quot;: {
    &quot;types&quot;: [
      &quot;lodash&quot;
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Note: No need to add each and every installed lodash method in here.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;import-methods-where-you-need-them&quot;&gt;Import methods where you need them&lt;/h2&gt;

&lt;p&gt;Just act like you have installed the whole Lodash package:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import { drop, dropRight } from &apos;lodash&apos;;

// […]
visiblePages = dropRight(totalPages, PagesAboveVisible);
&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;

&lt;p&gt;Looks easy, but I invested some time to get this straight. Hope this little tip can save you half an hour. :blush:&lt;/p&gt;
</description>
        <pubDate>Mon, 12 Jun 2017 11:00:00 +0000</pubDate>
        <link>http://michael-kuehnel.de/angular/2017/06/12/using-lodash-per-method-packages-with-angular-2-and-above.html</link>
        <guid isPermaLink="true">http://michael-kuehnel.de/angular/2017/06/12/using-lodash-per-method-packages-with-angular-2-and-above.html</guid>
        
        <category>Angular,</category>
        
        <category>Lodash,</category>
        
        <category>Quick</category>
        
        <category>Tip,</category>
        
        <category>npm,</category>
        
        <category>types,</category>
        
        <category>import</category>
        
        
        <category>Angular</category>
        
      </item>
    
      <item>
        <title>Cheat Sheet: Docker CLI</title>
        <description>&lt;div class=&quot;float-container&quot;&gt;
    &lt;img src=&quot;/assets/img/docker-logo.svg&quot; alt=&quot;&quot; class=&quot;float-left&quot; /&gt;
    &lt;div&gt;
        &lt;p&gt;
          I’m new to Docker. So this cheatsheet is primarily for me to help to remember commands for handling containers as well as images.
        &lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;See &lt;a href=&quot;https://docs.docker.com/engine/reference/commandline/&quot;&gt;Docker command line reference&lt;/a&gt; for the whole reference.&lt;/p&gt;

&lt;h1 id=&quot;containers&quot;&gt;Containers&lt;/h1&gt;

&lt;h2 id=&quot;listing-containers&quot;&gt;Listing containers&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;
# List running containers 
docker ps

# List all containers
docker ps -a	

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

&lt;h2 id=&quot;startingstopping-containers&quot;&gt;Starting/Stopping containers&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Start 
docker start containerName

# Stop
docker stop containerName
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;removing-containers&quot;&gt;Removing containers&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Remove container 
docker rm containerName

# Stop and remove container
docker rm -f containerName

# Remove all exited containers
docker rm -v $(docker ps -a -q -f status=exited)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;running-commands-in-new-containers&quot;&gt;Running commands in new containers&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker run imageName command arguments

# Example
docker run docker/whalesay cowsay Hello

# Assign a name to the container
docker run --name myName docker/whalesay cowsay Hello

# Run with a specific tag of an image
docker run node:6.9.1 node --version

# Run container in background
docker run -d -p 80:80 --name webserver nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;See &lt;a href=&quot;https://docs.docker.com/engine/reference/run/&quot;&gt;Docker run reference&lt;/a&gt; for more …&lt;/p&gt;

&lt;h1 id=&quot;images&quot;&gt;Images&lt;/h1&gt;

&lt;h2 id=&quot;listing-local-images&quot;&gt;Listing local images&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;removing-images&quot;&gt;Removing images&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker rmi imageName

# Remove unwanted dangling images
docker rmi $(docker images -f &quot;dangling=true&quot; -q)
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;searching-for-images&quot;&gt;Searching for images&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Search the Docker Hub for images
docker search searchWord
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;pulling-images&quot;&gt;Pulling images&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker pull imageName

# Pull a specific tag
docker pull imageName:tag

# Example: Get a specific node version
docker pull node:6.9.1
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;building-image-from-dockerfile&quot;&gt;Building image from Dockerfile&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker build .

# Name the image
docker build -t imageName .

# Tag the image
docker build -t imageName:1.0.0 .
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;See &lt;a href=&quot;https://docs.docker.com/engine/reference/builder/&quot;&gt;Dockerfile reference&lt;/a&gt; in addition.&lt;/p&gt;
</description>
        <pubDate>Sat, 19 Nov 2016 16:45:00 +0000</pubDate>
        <link>http://michael-kuehnel.de/docker/2016/11/19/docker-cli-cheatsheet.html</link>
        <guid isPermaLink="true">http://michael-kuehnel.de/docker/2016/11/19/docker-cli-cheatsheet.html</guid>
        
        <category>Docker,</category>
        
        <category>Cheat</category>
        
        <category>Sheet,</category>
        
        <category>CLI,</category>
        
        <category>Terminal,</category>
        
        <category>Command</category>
        
        <category>line</category>
        
        <category>interface</category>
        
        
        <category>Docker</category>
        
      </item>
    
      <item>
        <title>Data mocking – Ways to fake a backend (API)</title>
        <description>&lt;p&gt;&lt;em&gt;Eine deutsche Version des Artikels findet ihr im &lt;a href=&quot;https://labs.micromata.de/blog/fake-backend.html&quot;&gt;Micromata Blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Today we mostly have a loose coupling between the frontend and the backend of our web applications. It might be even useful to handle the separate parts as separate projects. Think about the backend as the provider of an RESTful API which has a totally different (hopefully semantic) versioning than the frontend. This offers much more flexibility by being able to deploy only the frontend to production or by using the same backend for a different frontend with a totally different tech stack (eg. native apps).&lt;/p&gt;

&lt;p&gt;So in development we have different people working on the frontend and on the backend. The backend team needs to make sure the content the API is providing is sane, whereas the frontend doesn’t care about the content: it just needs dummy data in the correct structure. So these teams only have to talk about and agree on JSON structures before they can work independently on their part.&lt;/p&gt;

&lt;p&gt;The main advantage working with dummy data over here is the independence in which the frontend team can work. It doesn’t matter if the development of the backend gets stuck for whatever reason.&lt;/p&gt;

&lt;p&gt;Which leads us to the question: &lt;em&gt;How could we simply mock the backend?&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;different-ways-to-fake-a-backend&quot;&gt;Different ways to fake a backend&lt;/h1&gt;

&lt;p&gt;There are a few possibilities to »serve« dummy data depending on your needs, your tech stack and the requirements of your project:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Static JSON files via Ajax&lt;/li&gt;
  &lt;li&gt;Online mocking services&lt;/li&gt;
  &lt;li&gt;»JSON Server«&lt;/li&gt;
  &lt;li&gt;An own server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are going to explore the details as well as the pros and cons of each and every possibility.&lt;/p&gt;

&lt;h2 id=&quot;loading-json-files-via-ajax&quot;&gt;Loading JSON files via Ajax&lt;/h2&gt;

&lt;p&gt;The simplest approach without any tooling involved. Just create your dummy data and store it within the file system of your frontend project.&lt;/p&gt;

&lt;h3 id=&quot;pros&quot;&gt;Pros&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Straightforward&lt;/li&gt;
  &lt;li&gt;The dummy data is in your version control system (eg. Git)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having those files in your file system has the big advantage, that the dummy data have a single source of truth. This is important for working in the team, especially for the coordination between the frontend and the backend team.&lt;/p&gt;

&lt;h3 id=&quot;cons&quot;&gt;Cons&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Very limited functionality&lt;/li&gt;
  &lt;li&gt;Might not be supported by your JavaScript Framework™&lt;/li&gt;
  &lt;li&gt;No usage of HTTP method besides &lt;code&gt;GET&lt;/code&gt; possible&lt;/li&gt;
  &lt;li&gt;Can’t test handling errors (besides 404)&lt;/li&gt;
  &lt;li&gt;Differences between the fake and the real backend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This might work out for a web app or website which just loads a little data via Ajax. But other than that the downsides will outweigh the simplicity in most cases. The biggest disadvantages are the differences between your fake backend and the real backend in production. This goes from different URLs (including a whole different structure) to different HTTP headers.&lt;/p&gt;

&lt;h2 id=&quot;online-mocking-services&quot;&gt;Online mocking services&lt;/h2&gt;

&lt;p&gt;There are dedicated services like &lt;a href=&quot;http://www.mockapi.io&quot;&gt;mockapi.io&lt;/a&gt;, &lt;a href=&quot;http://www.mocky.io&quot;&gt;mocky.io&lt;/a&gt; and &lt;a href=&quot;https://jsonstub.com/&quot;&gt;jsonstub.com&lt;/a&gt; which offer good solutions to help you effortlessly mock your HTTP responses.&lt;/p&gt;

&lt;h3 id=&quot;pros-1&quot;&gt;Pros&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Easy to use&lt;/li&gt;
  &lt;li&gt;Good and in some cases powerful configuration possibilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is almost as easy as storing JSON files in your project. Plus it offers more possibilities to configure things like HTTP status codes and verbs.&lt;/p&gt;

&lt;h3 id=&quot;cons-1&quot;&gt;Cons&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;CORS limitations (if applicable)&lt;/li&gt;
  &lt;li&gt;Your own data stored on public servers you don’t own&lt;/li&gt;
  &lt;li&gt;Dependent on vendor&lt;/li&gt;
  &lt;li&gt;Data isn’t in your version control system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dependency factor is important because it may lead to unforeseeable problems. There is a whole spectrum of uncertainties, mostly related to availability. You should ask yourself at least the following questions: Can I continue working when the service has downtimes? What happens if the service discontinues working? Will it offer any kind of export?&lt;/p&gt;

&lt;p&gt;Not having the dummy data under version control is also a major drawback if you are not working alone. Of course you could store the data redundantly in your file system; but that would lead to a maintainability overhead and might cause confusion because no one is sure whether the files in version control are really and exactly mirroring the data served by the mocking service.&lt;/p&gt;

&lt;h2 id=&quot;json-server&quot;&gt;»JSON Server«&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/typicode/json-server&quot;&gt;JSON Server&lt;/a&gt; is a nifty command line tool and super easy to use even for people who don’t spend most of the day at their terminals.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Get a full fake REST API with zero coding in less than 30 seconds (seriously)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It boils down to letting you serve JSON from your file system via a local server.&lt;/p&gt;

&lt;h3 id=&quot;pros-2&quot;&gt;Pros&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;The dummy data is in your version control system&lt;/li&gt;
  &lt;li&gt;The simplest setup you can imagine&lt;/li&gt;
  &lt;li&gt;It supports the most used http verbs&lt;/li&gt;
  &lt;li&gt;It saves changes to your JSON source for &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;PATCH&lt;/code&gt; or &lt;code&gt;DELETE&lt;/code&gt; requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This sounds like heaven. You can store your fake data in JSON in your project and have an external tool to provide the data.&lt;/p&gt;

&lt;p&gt;But there are also a few cons, one or the other of which might be a dealbreaker depending on your project requirements.&lt;/p&gt;

&lt;h3 id=&quot;cons-2&quot;&gt;Cons&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;The payload requires a strict format (JSON)&lt;/li&gt;
  &lt;li&gt;No routes with self-defined dynamic parts
    &lt;ul&gt;
      &lt;li&gt;&lt;del&gt;api/articles/{offset}/{count}&lt;/del&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Maintainability of one single JSON file for your responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s easy to use, however this means some of its conventions could get in your way.&lt;/p&gt;

&lt;p&gt;The payload restriction will be no problem if you have full control over the real backend as well. But you will have a problem when your real backend only accepts an integer as payload, to delete a data set for example.&lt;/p&gt;

&lt;p&gt;JSON server provides URL parameters for things like pagination. But this is bound to a fixed URL concept you have to adapt. Otherwise you end up having a huge list of URL mappings in a file called &lt;a href=&quot;https://github.com/typicode/json-server#add-routes&quot;&gt;routes.json&lt;/a&gt;. Having this option is advantageous but it may still lack flexibility depending on your needs.&lt;/p&gt;

&lt;p&gt;The last possible downside is that putting all your dummy data in one JSON file may not scale well.&lt;/p&gt;

&lt;h2 id=&quot;own-server&quot;&gt;Own server&lt;/h2&gt;

&lt;p&gt;Writing an own server just to provide your mocked data sounds like a perfect example of overengineering. The question is: Would you – as a frontend developer – maintain something like a »second« backend? Because the main reason to mock your data is to be independent of the backend.&lt;/p&gt;

&lt;p&gt;The answer is &lt;em&gt;yes&lt;/em&gt;, if you can have a reasonable compromise between flexibility and complexity.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/micromata/http-fake-backend&quot;&gt;http-fake-backend&lt;/a&gt; offers such compromise. It comes as a Node.js server which serves your dummy data via HTTP. And it’s almost as easy to set up as »JSON server«. It basically lets you build a fake backend by providing the content of JSON files or JavaScript objects through configurable routes.&lt;/p&gt;

&lt;p&gt;Each endpoint needs a configuration file to define routes, HTTP method and the response.&lt;/p&gt;

&lt;h3 id=&quot;simple-example&quot;&gt;Simple example&lt;/h3&gt;

&lt;p&gt;Let’s say you need an endpoint like &lt;code&gt;http://localhost:8081/api/simpleExample&lt;/code&gt; which should return:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;{
  &quot;status&quot;: &quot;ok&quot;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;All you have to do is create a configuration in a JavaScript file like:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;module.exports = SetupEndpoint({
    name: &apos;simpleExample&apos;,
    urls: [{
        requests: [{
          response: {status: &apos;ok&apos;}
        }]
    }]
});
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;advanced-example&quot;&gt;Advanced example&lt;/h3&gt;

&lt;p&gt;But it’s way more flexible than responding JSON defined through a JavaScript object via HTTP &lt;code&gt;GET&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s look at a more complex example configuration like the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;module.exports = SetupEndpoint({
    name: &apos;anotherExample&apos;,
    urls: [{
        params: &apos;/read&apos;,
        requests: [{
            method: &apos;GET&apos;,
            response: &apos;/json-templates/anotherExample.json&apos;
        }]
    }, {
        params: &apos;/update/{id}&apos;,
        requests: [{
            method: [&apos;PUT&apos;, &apos;PATCH&apos;],
            response: {
                success: true
            }
        }, {
            method: &apos;DELETE&apos;,
            response: {
                deleted: true
            }
        }]
    }]
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So you can have multiple urls with different HTTP verbs for any endpoint and you can define your Response via JSON files.&lt;/p&gt;

&lt;p&gt;You can also fake HTTP errors and status codes for an entire endpoint or on request level like in the following example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;module.exports = SetupEndpoint({
    name: &apos;statusCodes&apos;,
    urls: [
        {
            params: &apos;/boomError&apos;,
            requests: [{
                // Returns a 402 status code + error message provided by boom:
                // {
                //   &quot;error&quot; : &quot;Payment Required&quot;,
                //   &quot;statusCode&quot; : 402
                // }
                statusCode: 402
            }]
        },
        {
            params: &apos;/customError&apos;,
            requests: [{
                // Returns a HTTP status code 406 and a self defined response:
                response: { error: true },
                statusCode: 406
            }]
        },
        {
            params: &apos;/regularResponse&apos;,
            requests: [{
                // Returns a 401 error provided by boom
                // as defined on endpoint level
                response: &apos;/json-templates/anotherExample.json&apos;
            }]
        }
    ],
    statusCode: 401
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The configuration object described in detail:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;name&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Is used to set the endpoint.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;urls&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;You need to add at least one url object.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;urls.params&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Optional&lt;/li&gt;
      &lt;li&gt;In this example a valid URL might be:
&lt;code&gt;http://localhost:8081/api/articles/foo/bar/baz&lt;/code&gt;
whereas:
&lt;code&gt;http://localhost:8081/api/articles&lt;/code&gt; will return a 404 error.&lt;/li&gt;
      &lt;li&gt;See hapi docs. For example regarding optional &lt;a href=&quot;http://hapijs.com/api#path-parameters&quot;&gt;path parameters&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;urls.requests&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;You need to add at least one request object.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;urls.requests.method&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;optional. Uses &lt;code&gt;GET&lt;/code&gt; when not defined.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;string&lt;/code&gt;, or &lt;code&gt;array&lt;/code&gt; of strings.&lt;/li&gt;
      &lt;li&gt;is used to define the http method(s) to which the endpoint will listen.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;urls.requests.response&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Could be a string pointing to a JSON template:
        &lt;ul&gt;
          &lt;li&gt;&lt;code&gt;response: &apos;/json-templates/articles.json&apos;&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Or just a JavaScript object:
        &lt;ul&gt;
          &lt;li&gt;&lt;code&gt;response: { success: true }&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;urls.requests.statusCode&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Optional&lt;/li&gt;
      &lt;li&gt;A status code (number)&lt;/li&gt;
      &lt;li&gt;Will return:
        &lt;ul&gt;
          &lt;li&gt;a status code with a self defined response if you provide a response property&lt;/li&gt;
          &lt;li&gt;a status code with a predefined error object provided by &lt;a href=&quot;https://github.com/hapijs/boom&quot;&gt;boom&lt;/a&gt; if you dont provide a response property for that request.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code&gt;statusCode&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;Optional&lt;/li&gt;
      &lt;li&gt;Every route of this endpoint will return a HTTP error with the given status code provided by &lt;a href=&quot;https://github.com/hapijs/boom&quot;&gt;boom&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;People who think that this looks daunting can create a config like this easily and interactively with the help of this &lt;a href=&quot;https://github.com/micromata/generator-http-fake-backend&quot;&gt;Yeoman generator&lt;/a&gt; which comes with a subgenerator which guides through the configuration:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/441011/19894056/ce7c4ece-a04b-11e6-9cc0-a30429d98b6f.gif&quot; alt=&quot;yeoman&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;it-offers-even-more-flexibility&quot;&gt;It offers even more flexibility&lt;/h3&gt;

&lt;p&gt;Just when you need it: You can build own endpoints with custom configs since the server underneath is just a simple http server built with &lt;a href=&quot;http://hapijs.com/&quot;&gt;hapi&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;pros-3&quot;&gt;Pros&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;The dummy data is in your version control system&lt;/li&gt;
  &lt;li&gt;The highest flexibility&lt;/li&gt;
  &lt;li&gt;Easy setup of
    &lt;ul&gt;
      &lt;li&gt;Endpoints&lt;/li&gt;
      &lt;li&gt;URLs including dynamic parts&lt;/li&gt;
      &lt;li&gt;allowed HTTP methods&lt;/li&gt;
      &lt;li&gt;errors (supporting all HTTP status codes)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Yeoman generator
    &lt;ul&gt;
      &lt;li&gt;with a subgenerator to assist with building the API&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also optionally restarts the server when JSON or config files are changed. Just like JSON server.&lt;/p&gt;

&lt;h3 id=&quot;cons-3&quot;&gt;Cons&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Slightly more complex setup compared to JSON server&lt;/li&gt;
  &lt;li&gt;Less intelligent than JSON server
    &lt;ul&gt;
      &lt;li&gt;No persisting of payload data for POST, PUT and PATCH requests&lt;/li&gt;
      &lt;li&gt;No automatic and real relation between data of different endpoints
        &lt;ul&gt;
          &lt;li&gt;Example:
            &lt;ul&gt;
              &lt;li&gt;You have to define own and independent data for a route which returns a list &lt;code&gt;/api/products&lt;/code&gt; and a route which returns a single item &lt;code&gt;/api/products/{id}&lt;/code&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;workflow-integration&quot;&gt;Workflow integration&lt;/h3&gt;

&lt;p&gt;Starting the server is as easy as firing &lt;code&gt;npm run start:dev&lt;/code&gt; during development or &lt;code&gt;npm start&lt;/code&gt; in a Continuous Integration environment. No matter if you are using npm run scripts or a workflow based on a taskrunner to build your frontend.&lt;/p&gt;

&lt;h3 id=&quot;getting-started&quot;&gt;Getting started&lt;/h3&gt;

&lt;p&gt;Just visit the projects &lt;a href=&quot;https://github.com/micromata/http-fake-backend&quot;&gt;Github page&lt;/a&gt; and you will have your fake backend running in a couple of minutes. You are even faster when using the &lt;a href=&quot;https://github.com/micromata/generator-http-fake-backend&quot;&gt;Yeoman Generator&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;helpers-for-generating-your-dummy-data&quot;&gt;Helpers for generating your dummy data&lt;/h2&gt;

&lt;p&gt;Developers aren’t lazy per se. But we all like to dispense with stupid and repetitive work. So we could need some help generating the content for our fake backend. This is where the following tools might come in handy.&lt;/p&gt;

&lt;h3 id=&quot;json-generators&quot;&gt;JSON generators&lt;/h3&gt;

&lt;p&gt;The following tools could help you to generate JSON files for fake backend:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/danibram/mocker-data-generator&quot;&gt;https://github.com/danibram/mocker-data-generator&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.json-generator.com&quot;&gt;http://www.json-generator.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;dummy-data-generators&quot;&gt;Dummy data generators&lt;/h3&gt;

&lt;p&gt;Feel free to use one of these excellent node modules if you prefer to build the responses of your fake backend programmatically:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Marak/faker.js&quot;&gt;https://github.com/Marak/faker.js&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/boo1ean/casual&quot;&gt;https://github.com/boo1ean/casual&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/chancejs/chancejs&quot;&gt;https://github.com/chancejs/chancejs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Fri, 04 Nov 2016 00:10:00 +0000</pubDate>
        <link>http://michael-kuehnel.de/api/2016/11/04/data-mocking-ways-to-fake-a-backend-api.html</link>
        <guid isPermaLink="true">http://michael-kuehnel.de/api/2016/11/04/data-mocking-ways-to-fake-a-backend-api.html</guid>
        
        <category>Data,</category>
        
        <category>Mocking,</category>
        
        <category>Rest,</category>
        
        <category>JSON,</category>
        
        <category>API,</category>
        
        <category>Frontend,</category>
        
        <category>Backend,</category>
        
        <category>Fake,</category>
        
        <category>Testing</category>
        
        
        <category>API</category>
        
      </item>
    
      <item>
        <title>Switch Node.js versions with the Node Version Manager (nvm)</title>
        <description>&lt;h2 id=&quot;update-from-june-2-2016&quot;&gt;Update from June 2, 2016&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Update versions numbers in examples&lt;/li&gt;
  &lt;li&gt;Add info about &lt;a href=&quot;#so-many-versions-flushed&quot;&gt;getting version infos&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Add note about &lt;a href=&quot;#potential-problems-with-linking-global-packages&quot;&gt;potential problems with linking global packages&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Complete info about handling of &lt;a href=&quot;#globally-installed-packages&quot;&gt;globally installed packages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;div class=&quot;float-container&quot;&gt;
    &lt;img src=&quot;/assets/img/nodejs-logo.svg&quot; alt=&quot;&quot; class=&quot;float-left&quot; /&gt;
    &lt;div&gt;
        &lt;p&gt;
          Sure you can just use homebrew to update your Node.js installation when there are new releases. It’s in fact very handy to do so. But beside the quirk when it comes to updating npm there is a method which makes switching Node.js version even easier. This became more important since the stable release of Node 4.0 which I like to use. But I have to be able to use a different Node version just in case thinks break with Node 4.0.
        &lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;h1 id=&quot;uninstall-node-via-homebrew&quot;&gt;Uninstall node via homebrew&lt;/h1&gt;

&lt;p&gt;First we could check which version of node we are using:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ node -v
v5.5.0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let’s get rid of this and older versions in the cellar of homebrew:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ brew uninstall --force node
Uninstalling node...
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;potential-problems-with-linking-global-packages&quot;&gt;Potential problems with linking global packages&lt;/h2&gt;

&lt;p&gt;Double check if there still is a &lt;code&gt;node_modules&lt;/code&gt; directory in &lt;code&gt;/usr/local/lib&lt;/code&gt; holding your globally installed packages. Do yourself a favor and remove that to prevent possible issues with linking globale packages via &lt;code&gt;npm link&lt;/code&gt;.&lt;/p&gt;

&lt;h1 id=&quot;installing-the-node-version-manager-nvm&quot;&gt;Installing the Node Version Manager (nvm)&lt;/h1&gt;

&lt;p&gt;I prefer installing it via homebrew:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ brew update
$ brew install nvm
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Please have a look at &lt;a href=&quot;https://github.com/creationix/nvm&quot;&gt;https://github.com/creationix/nvm&lt;/a&gt; in case you would like to do a manual install.&lt;/p&gt;

&lt;p&gt;Either way you have to add a few lines to your &lt;code&gt;~/.bash_profile&lt;/code&gt;, &lt;code&gt;~/.zshrc&lt;/code&gt; or &lt;code&gt;~/.profile&lt;/code&gt;. In case of the homebrew installation it is:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;export NVM_DIR=~/.nvm
source $(brew --prefix nvm)/nvm.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&quot;using-nvm&quot;&gt;Using nvm&lt;/h1&gt;

&lt;p&gt;To download, compile, and install the (currently) latest v6.x.x release of node, do this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nvm install 6
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let’s install the latest v5.x.x release in addition:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nvm install 5
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You will use the latest installed version automatically after installation.
Switching version is easy as:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nvm use 6
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In place of a version pointer like “6”, you can use the special default aliases like “stable” and “unstable”:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nvm install stable
nvm install unstable
nvm use stable
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;globally-installed-packages&quot;&gt;Globally installed packages&lt;/h2&gt;

&lt;p&gt;Please note that you have to install global packages with every node version your are using with nvm.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Another day, another Node.js release”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is something you want to automate since releases of Node.js are pretty frequent (for a good reason). Thankfully nvm offers to ways to accomplish that.&lt;/p&gt;

&lt;h1 id=&quot;reinstall-during-install&quot;&gt;Reinstall during install&lt;/h1&gt;

&lt;p&gt;The easiest one is to take care of that after during installation of a new node version with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nvm install node --reinstall-packages-from=node
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will install the latest release and reinstall the globally installed packages from the predecessor.&lt;/p&gt;

&lt;p&gt;You also can use more explicit versions like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nvm install 6.2 --reinstall-packages-from=6.0
&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&quot;reinstall-later&quot;&gt;Reinstall later&lt;/h1&gt;

&lt;p&gt;You can »transfer« your global packages from one version to another at any given time. Just use:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nvm reinstall-packages &amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will reinstall global packages contained in &lt;code&gt;&amp;lt;version&amp;gt;&lt;/code&gt;  to the current version in use.&lt;/p&gt;

&lt;h2 id=&quot;setting-a-default-version&quot;&gt;Setting a default version&lt;/h2&gt;

&lt;p&gt;You need to set a default version if you dont want to be surprised by switched versions with every opened Terminal window/tab. There are the two following ways to accomplish this.&lt;/p&gt;

&lt;h3 id=&quot;via-config-file&quot;&gt;Via config file&lt;/h3&gt;

&lt;p&gt;You can place a &lt;code&gt;.nvmrc&lt;/code&gt; file in your home directory to define your prefered version globally. For example:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;5
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This can be overidden by placing other &lt;code&gt;.nvmrc&lt;/code&gt; files in your project root directories.&lt;/p&gt;

&lt;h3 id=&quot;via-nvm-alias&quot;&gt;Via nvm alias&lt;/h3&gt;

&lt;p&gt;Alternatively you can add an alias with &lt;code&gt;nvm alias &amp;lt;name&amp;gt; &amp;lt;version&amp;gt; &lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ nvm alias default 5
default -&amp;gt; 5 (-&amp;gt; v5.11.1)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Enter &lt;code&gt;nvm --help&lt;/code&gt; to see how to handle aliases.&lt;/p&gt;

&lt;h2 id=&quot;so-many-versions-flushed&quot;&gt;So many versions :flushed:&lt;/h2&gt;

&lt;p&gt;After a few releases it might come in handy to check which versions are installed and which you are currently using.&lt;/p&gt;

&lt;p&gt;Just enter the following to see which versions are installed:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ nvm ls
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will also highlight the version currently in use.&lt;/p&gt;

&lt;p&gt;You could also fire &lt;code&gt;nvm current&lt;/code&gt; to see what version your are using.&lt;/p&gt;

&lt;h3 id=&quot;showing-the-current-version-in-your-prompt&quot;&gt;Showing the current version in your prompt&lt;/h3&gt;

&lt;p&gt;There are zsh themes like &lt;a href=&quot;https://github.com/caiogondim/bullet-train-oh-my-zsh-theme#nodejs-nvm&quot;&gt;Bullet Train&lt;/a&gt; which offer to make the version visible with every prompt.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/nvm-screenshot.png&quot; alt=&quot;Screenshot&quot; /&gt;
Pretty nifty, huh?&lt;/p&gt;

&lt;p&gt;I guess that’s all you need to know to start using nvm. 
Make sure to checked out the &lt;a href=&quot;https://github.com/creationix/nvm&quot;&gt;project on Github&lt;/a&gt; in case you like to dig deeper.&lt;/p&gt;

</description>
        <pubDate>Tue, 08 Sep 2015 23:00:00 +0000</pubDate>
        <link>http://michael-kuehnel.de/node.js/2015/09/08/using-vm-to-switch-node-versions.html</link>
        <guid isPermaLink="true">http://michael-kuehnel.de/node.js/2015/09/08/using-vm-to-switch-node-versions.html</guid>
        
        <category>Quick</category>
        
        <category>Tip,</category>
        
        <category>Node.js,</category>
        
        <category>Versions,</category>
        
        <category>homebrew,</category>
        
        <category>npm</category>
        
        
        <category>Node.js</category>
        
      </item>
    
      <item>
        <title>Quick Tip: Updating your node modules is easy as »1, 2, 3«</title>
        <description>&lt;div class=&quot;float-container&quot;&gt;
    &lt;img src=&quot;/assets/img/npm-logo.svg&quot; alt=&quot;&quot; class=&quot;float-left&quot; /&gt;
    &lt;div&gt;
        &lt;p&gt;
          It might be a »no-brainer« in case you are working within the Node.js environment for a while. But I used to ask myself how to figure out if there are updates to my dependencies / devDependencies which are beyond the patch-level updates which are »automatically« installed via the definition within my `package.json`. Because I don’t like to check possible updates separately for every module I’m using in my project.
        &lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Fortunately there is a node module which can handle that for all dependencies within your project and even all your globale modules. It’s called &lt;a href=&quot;https://www.npmjs.com/package/npm-check-updates&quot;&gt;npm-check-updates&lt;/a&gt; and will also update your &lt;code&gt;package.json&lt;/code&gt; file if you like to. So updating becomes »fun« again :smile:&lt;/p&gt;

&lt;p&gt;Using this is pretty straight forward. First you need to install the package globally with:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install -g npm-check-updates
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then use the modules cli without any option to check available updates within your projects root directory:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm-check-updates
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will show you all possible updates without changing anything:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&quot;superb&quot; can be updated from ^1.0.5 to ^1.1.1 (Installed: 1.0.5, Latest: 1.1.1)
&quot;mocha&quot; can be updated from ^2.0.1 to ^2.1.0 (Installed: 2.0.1, Latest: 2.1.0)
&quot;should&quot; can be updated from ^4.4.2 to ^4.6.1 (Installed: 4.4.2, Latest: 4.6.1)

Run &apos;npm-check-updates -u&apos; to upgrade your package.json automatically
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If you like to upgrade your projects &lt;code&gt;package.json&lt;/code&gt; file just make use of the &lt;code&gt;-u&lt;/code&gt; option as mentioned in the output above and fire:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;afterwards. And :boom: … all updates will land on your machine and you’re done.&lt;/p&gt;

&lt;p&gt;See the &lt;a href=&quot;https://www.npmjs.com/package/npm-check-updates&quot;&gt;README&lt;/a&gt; for more options.&lt;/p&gt;
</description>
        <pubDate>Tue, 20 Jan 2015 14:00:00 +0000</pubDate>
        <link>http://michael-kuehnel.de/npm/2015/01/20/check-updates-of-your-node-modules.html</link>
        <guid isPermaLink="true">http://michael-kuehnel.de/npm/2015/01/20/check-updates-of-your-node-modules.html</guid>
        
        <category>Quick</category>
        
        <category>Tip,</category>
        
        <category>npm,</category>
        
        <category>Node.js,</category>
        
        <category>update</category>
        
        
        <category>npm</category>
        
      </item>
    
      <item>
        <title>Quick Tip: Update your Git client on Mac OS X</title>
        <description>&lt;div class=&quot;float-container&quot;&gt;
    &lt;img src=&quot;/assets/img/git-logo.png&quot; alt=&quot;&quot; class=&quot;float-left&quot; /&gt;
    &lt;div&gt;
        &lt;p&gt;
          I like to assist you just in case you wonder how to react on yesterdays announcement of that critical Git security vulnerability. As said within this &lt;a href=&quot;https://github.com/blog/1938-vulnerability-announced-update-your-git-clients&quot;&gt;post&lt;/a&gt; on Githubs Blog it’s strongly recommended to update your Git clients as soon as possible. Here we go with a short instruction how to update in case you are using OS X.
        &lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;h2 id=&quot;1-if-youre-already-using-homebrew&quot;&gt;1. If you’re already using Homebrew&lt;/h2&gt;

&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;`brew update &amp;amp;&amp;amp; brew upgrade git` or `brew update &amp;amp;&amp;amp; brew install git`
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Entering &lt;code&gt;git --version&lt;/code&gt; should echo → &lt;code&gt;git version 2.14.1&lt;/code&gt; afterwards.&lt;/p&gt;

&lt;p&gt;In case it’s saying something like &lt;code&gt;Git 1.9.x (Apple)&lt;/code&gt; instead you have to add &lt;code&gt;export PATH=/usr/local/bin:$PATH&lt;/code&gt; to your environment variables via &lt;code&gt;.bashrc&lt;/code&gt; or however you handle that. See &lt;a href=&quot;https://github.com/mischah/dotfiles/commit/44fae96e96b5721c0e349fafdc1172e78278979c&quot;&gt;my dotfiles&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After restarting your terminal  &lt;code&gt;git --version&lt;/code&gt; should print → &lt;code&gt;git version 2.14.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And you’re safe using Git via the command line.&lt;/p&gt;

&lt;h2 id=&quot;2-if-you-dont-use-homebrew&quot;&gt;2. If you don’t use Homebrew&lt;/h2&gt;

&lt;p&gt;Get &lt;a href=&quot;http://brew.sh/&quot;&gt;Homebrew&lt;/a&gt; and start reading at »&lt;a href=&quot;#if-youre-already-using-homebrew&quot;&gt;1. If your already using Homebrew&lt;/a&gt;«.&lt;/p&gt;

&lt;h2 id=&quot;update-your-git-gui&quot;&gt;Update your Git Gui&lt;/h2&gt;

&lt;p&gt;In case you’re a using a Git client like Tower oder SourceTree you have to tell those apps which Git version they should use. You can set this via the Applications Preferences hitting &lt;code&gt;⌘ + ,&lt;/code&gt; on your Keyboard.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;That’s it. Happy coding and merry christmas :christmas_tree:&lt;/p&gt;
</description>
        <pubDate>Fri, 19 Dec 2014 12:00:00 +0000</pubDate>
        <link>http://michael-kuehnel.de/git/2014/12/19/update-your-git-client-on-mac-os-x.html</link>
        <guid isPermaLink="true">http://michael-kuehnel.de/git/2014/12/19/update-your-git-client-on-mac-os-x.html</guid>
        
        <category>Quick</category>
        
        <category>Tip,</category>
        
        <category>Git,</category>
        
        <category>Mac</category>
        
        <category>OS</category>
        
        <category>X,</category>
        
        <category>Security</category>
        
        
        <category>Git</category>
        
      </item>
    
  </channel>
</rss>
