<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: unhurried</title>
    <description>The latest articles on DEV Community by unhurried (@unhurried).</description>
    <link>https://dev.to/unhurried</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F215099%2Ff1470308-5d97-4486-96d6-cde997bcf027.jpeg</url>
      <title>DEV Community: unhurried</title>
      <link>https://dev.to/unhurried</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/unhurried"/>
    <language>en</language>
    <item>
      <title>TypeScript REST API Client</title>
      <dc:creator>unhurried</dc:creator>
      <pubDate>Fri, 22 May 2020 21:44:13 +0000</pubDate>
      <link>https://dev.to/unhurried/typescript-rest-api-client-4in3</link>
      <guid>https://dev.to/unhurried/typescript-rest-api-client-4in3</guid>
      <description>&lt;p&gt;In this article, I will introduce a list of REST API client libraries I've researched which can be used in TypeScript (browser or  Node.js).&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/axios/axios"&gt;axios&lt;/a&gt; and &lt;a href="https://github.com/Microsoft/typed-rest-client"&gt;typed-rest-client&lt;/a&gt; have many users and stable development activities.

&lt;ul&gt;
&lt;li&gt;As of Nov. 2019, axios is more popular than typed-rest-client. However, typed-rest-client might be going to get popularity in the future as it is maintained by Microsoft, that also maintains TypeScript.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch"&gt;Fetch API&lt;/a&gt;, which is a good option based on Web standard is not fully supported in all browsers, and some additional codes are required to support types.

&lt;ul&gt;
&lt;li&gt;Using &lt;a href="https://github.com/github/fetch"&gt;Polyfill&lt;/a&gt; would solve the browser support problem.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Generating client SDK with &lt;a href="https://openapi-generator.tech/"&gt;OpenAPI Generator&lt;/a&gt; will save a lot when OpenAPI (Swagger) spec is available.

&lt;ul&gt;
&lt;li&gt;OpenAPI Generator is a project that was forked from &lt;a href="https://swagger.io/tools/swagger-codegen/"&gt;Swagger Codegen&lt;/a&gt; and maintained by a community. It has more active development and more generators than Swagger Codegen. (cf. &lt;a href="https://openapi-generator.tech/docs/fork-qna"&gt;Swagger Codegen Fork: Q&amp;amp;A&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Generators for TypeScript provided by OpenAPI Generator includes &lt;a href="https://openapi-generator.tech/docs/generators/typescript-axios"&gt;typescript-axios&lt;/a&gt;, &lt;a href="https://openapi-generator.tech/docs/generators/typescript-fetch"&gt;typescript-fetch&lt;/a&gt; and &lt;a href="https://openapi-generator.tech/docs/generators/typescript-angular"&gt;typescript-anglar&lt;/a&gt;, that is made especially for Angular framework. (cf. &lt;a href="https://openapi-generator.tech/docs/generators#client-generators"&gt;Generators List&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Examples of Using Libraries
&lt;/h3&gt;

&lt;h4&gt;
  
  
  OpenAPI Generator
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Generate a Client SDK
&lt;/h5&gt;

&lt;p&gt;CLI tool can be install in various ways such as NPM or Docker image. (cf. &lt;a href="https://openapi-generator.tech/docs/installation.html"&gt;CLI Installation&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Generators that don't depend on a specific framework are the ones using axios or Fetch API. As I mentioned earlier, I chose &lt;a href="https://openapi-generator.tech/docs/generators/typescript-axios"&gt;typescript-axios&lt;/a&gt;. You can generate a client SDK in your src directory with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openapi-generator generate &lt;span class="nt"&gt;-g&lt;/span&gt; typescript-axios &lt;span class="nt"&gt;-i&lt;/span&gt; ./openapi.yaml &lt;span class="nt"&gt;-o&lt;/span&gt; ./src/client-axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Call an API with SDK
&lt;/h5&gt;

&lt;p&gt;You can change the base URL when a URL specified in OpenAPI document is different from the actual one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DefaultApi&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/client-axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;DefaultApi&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;basePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;baseUrl&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;getToDo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In case generated codes violate linter rules in your project, you need to configure the linter to ignore them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .eslintignore&lt;/span&gt;
src/client-axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, when your project uses webpack and configures the type definition to use only &lt;code&gt;webpack-env&lt;/code&gt;, you need to add a type definitions of Node.js modules because generated codes use url module in Node.js. (cf. &lt;a href="https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#types-typeroots-and-types"&gt;TypeScript Configuration Reference&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tsconfig.json&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;compilerOptions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;webpack-env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  axios
&lt;/h4&gt;

&lt;p&gt;Define interface for response bodies and pass them as type parameters in axios API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Todo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://jsonplaceholder.typicode.com/todos/1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Todo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reference
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;How to generate client libraries from OpenAPI

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.5thfloor.co.jp/2019/06/26/webapp-development-with-openapi-and-typescript/#openapi-generator-api-"&gt;https://blog.5thfloor.co.jp/2019/06/26/webapp-development-with-openapi-and-typescript/#openapi-generator-api-&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ky-yk-d.hatenablog.com/entry/2019/01/13/234108"&gt;https://ky-yk-d.hatenablog.com/entry/2019/01/13/234108&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vuejs.org/v2/cookbook/using-axios-to-consume-apis.html"&gt;Vue.js Cookbook&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt; It recommends axios as there still are some problems with Fetch API.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
    </item>
    <item>
      <title>[TypeScript] Implement valueOf method in Enums</title>
      <dc:creator>unhurried</dc:creator>
      <pubDate>Thu, 09 Jan 2020 11:43:30 +0000</pubDate>
      <link>https://dev.to/unhurried/typescript-implement-valueof-method-in-enums-2gme</link>
      <guid>https://dev.to/unhurried/typescript-implement-valueof-method-in-enums-2gme</guid>
      <description>&lt;p&gt;Enums in Typescript don't have valueOf method, which returns an enum element from its string representation. This article explains how we can add valueOf method to Enums. Note that the implementation suggested in this article uses namespace as we cannot add arbitrary methods to Enums.&lt;/p&gt;

&lt;h5&gt;
  
  
  Numeric Enum
&lt;/h5&gt;

&lt;p&gt;Numeric Enums, which assign incremental numbers to their elements, support reverse mapping . Therefore valueOf method can be implemented with &lt;code&gt;Enum[string]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However we need to use one of the following expressions as  &lt;code&gt;Enum[string]&lt;/code&gt; produces a type error which says "Element implicitly has an 'any' type...".&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Enum[string as keyof typeof Enum]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(&amp;lt;any&amp;gt;Enum)[string]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h6&gt;
  
  
  Implementation Example
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* Numeric Enum */&lt;/span&gt;
&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Color&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Red&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Green&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// toString()&lt;/span&gt;
&lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Green&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; '1'&lt;/span&gt;
&lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Green&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 'Green'&lt;/span&gt;

&lt;span class="c1"&gt;// valueOf()&lt;/span&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;Color&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; NumericEnum.Green&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  String Enum
&lt;/h5&gt;

&lt;p&gt;String Enums, to which we can assign arbitrary string representations to their elements, don't support reverse mapping (*). Therefore we need to prepare a map object for reverse mapping by ourselves.&lt;/p&gt;

&lt;h6&gt;
  
  
  Implementation Example
&lt;/h6&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/* String Enum */&lt;/span&gt;
&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Color&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Red&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Green&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// toString()&lt;/span&gt;
&lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Green&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 'green'&lt;/span&gt;

&lt;span class="c1"&gt;// valueOf()&lt;/span&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nx"&gt;Color&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reverseMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;reverseMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;reverseMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valueOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; StringEnum.Green&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;* Enum elements can be retrieved by their key names just like numeric enums, but not by strings that are assigned to enum elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; Color.Green&lt;/span&gt;
&lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;keyof&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Reference
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/enums.html"&gt;Enums - TypeScript Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://typescript-jp.gitbook.io/deep-dive/type-system/enums#wotsuenum-with-static-functions"&gt;Enum with static functions - TypeScript Deep Dive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/17380845/how-do-i-convert-a-string-to-enum-in-typescript"&gt;How do I convert a string to enum in TypeScript? - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/44883072/reverse-mapping-for-string-enums"&gt;Reverse-Mapping for String Enums - Stack Overflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Microsoft/TypeScript/issues/20813"&gt;#20813 Iterating on a string enum - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
      <category>enum</category>
    </item>
    <item>
      <title>How to Change Key Bindings of vim-mode-plus</title>
      <dc:creator>unhurried</dc:creator>
      <pubDate>Fri, 25 Oct 2019 10:36:55 +0000</pubDate>
      <link>https://dev.to/unhurried/how-to-change-key-bindings-of-vim-mode-plus-4970</link>
      <guid>https://dev.to/unhurried/how-to-change-key-bindings-of-vim-mode-plus-4970</guid>
      <description>&lt;p&gt;vim-mode-plus, which is a plugin for Atom editor doesn't have a feature to load vimrc files that are common in Vim editor. Therefore, we need to prepare keymap.cson, which is the keymap configuration file of Atom and init.coffee, which is an initial configuration file of Atom, to assign multiple commands to one command.&lt;/p&gt;

&lt;p&gt;I will introduce an example that converts a vimrc file to init.coffee and keymap.cson.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before Conversion
&lt;/h3&gt;

&lt;h4&gt;
  
  
  vimrc
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;noremap j gj
noremap k gk

noremap &amp;lt;S-j&amp;gt; 10j
noremap &amp;lt;S-k&amp;gt; 10k
noremap &amp;lt;S-h&amp;gt; 10h
noremap &amp;lt;S-l&amp;gt; 10l
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  After Conversion
&lt;/h3&gt;

&lt;h4&gt;
  
  
  init.coffee
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight coffeescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt; &lt;span class="s"&gt;'atom-text-editor.vim-mode-plus'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'custom:move-left-10'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getView&lt;/span&gt; &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getActiveTextEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'vim-mode-plus:set-count-1'&lt;/span&gt;
  &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'vim-mode-plus:set-count-0'&lt;/span&gt;
  &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'vim-mode-plus:move-left'&lt;/span&gt;

&lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt; &lt;span class="s"&gt;'atom-text-editor.vim-mode-plus'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'custom:move-down-screen-10'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getView&lt;/span&gt; &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getActiveTextEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'vim-mode-plus:set-count-1'&lt;/span&gt;
  &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'vim-mode-plus:set-count-0'&lt;/span&gt;
  &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'vim-mode-plus:move-down-screen'&lt;/span&gt;

&lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt; &lt;span class="s"&gt;'atom-text-editor.vim-mode-plus'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'custom:move-up-screen-10'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getView&lt;/span&gt; &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getActiveTextEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'vim-mode-plus:set-count-1'&lt;/span&gt;
  &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'vim-mode-plus:set-count-0'&lt;/span&gt;
  &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'vim-mode-plus:move-up-screen'&lt;/span&gt;

&lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt; &lt;span class="s"&gt;'atom-text-editor.vim-mode-plus'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'custom:move-right-10'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;views&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getView&lt;/span&gt; &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getActiveTextEditor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'vim-mode-plus:set-count-1'&lt;/span&gt;
  &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'vim-mode-plus:set-count-0'&lt;/span&gt;
  &lt;span class="nx"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'vim-mode-plus:move-right'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  keymap.cson
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'atom-text-editor.vim-mode-plus:not(.insert-mode)':
  'shift-h': 'custom:move-left-10'
  'shift-j': 'custom:move-down-screen-10'
  'shift-k': 'custom:move-up-screen-10'
  'shift-l': 'custom:move-right-10'
  'h': 'vim-mode-plus:move-left'
  'j': 'vim-mode-plus:move-down-screen'
  'k': 'vim-mode-plus:move-up-screen'
  'l': 'vim-mode-plus:move-right'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>vim</category>
      <category>atom</category>
    </item>
    <item>
      <title>How to Set Up Vim Key Bindings in Atom</title>
      <dc:creator>unhurried</dc:creator>
      <pubDate>Fri, 25 Oct 2019 10:31:31 +0000</pubDate>
      <link>https://dev.to/unhurried/how-to-set-up-vim-key-bindings-in-atom-bj0</link>
      <guid>https://dev.to/unhurried/how-to-set-up-vim-key-bindings-in-atom-bj0</guid>
      <description>&lt;p&gt;I have been using Vim editor since I was a university student. However I start to think that Atom editor which has various plugins is more convenient in many cases.&lt;/p&gt;

&lt;p&gt;To migrate from Vim to Atom smoothly, I've researched how to configure Vim key bindings in Atom.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Plugins
&lt;/h3&gt;

&lt;p&gt;vim-mode-plus and ex-mode are recommended.&lt;/p&gt;

&lt;p&gt;Note: vim-mode and vim-mode-plus-ex-mode are deprecated.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://atom.io/packages/vim-mode"&gt;https://atom.io/packages/vim-mode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://atom.io/packages/vim-mode-plus-ex-mode"&gt;https://atom.io/packages/vim-mode-plus-ex-mode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Turn off IME when exit the insert mode with Esc
&lt;/h3&gt;

&lt;p&gt;We need to use several 3rd party applications to change the key bindings because Atom plugins can not turn off IME.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Karabiner (for MacOS) or AutoHotKey (for Windows) seem to be popular.
(However, these applications cannot reset IME when we enter the insert mode again.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Configure key bindings for plugins
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You need to define key bindings in keymap.cson as vim-mode-plus doesn't have a feature to load vimrc files.&lt;/li&gt;
&lt;li&gt;If you need to issue multiple commands in a key binding, you need to register a custom command in init.coffee.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>atom</category>
      <category>vim</category>
    </item>
    <item>
      <title>Convert Markdown into HTML with Sphinx</title>
      <dc:creator>unhurried</dc:creator>
      <pubDate>Fri, 04 Oct 2019 09:42:05 +0000</pubDate>
      <link>https://dev.to/unhurried/convert-markdown-into-html-with-sphinx-3hf5</link>
      <guid>https://dev.to/unhurried/convert-markdown-into-html-with-sphinx-3hf5</guid>
      <description>&lt;p&gt;Little notes of a study on a method to convert a markdown file into a HTML file with Sphinx. You can find the deliverable of this study in &lt;a href="https://github.com/unhurried/sphinx-with-markdown"&gt;sphinx-with-markdown&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Enable markdown syntax in Sphinx
&lt;/h4&gt;

&lt;p&gt;Install &lt;a href="https://recommonmark.readthedocs.io/en/stable/"&gt;recommonmark&lt;/a&gt; and register it as a markdown parser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;recommonmark
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;conf.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;source_suffix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'.rst'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'.md'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;source_parsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="s"&gt;'.md'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'recommonmark.parser.CommonMarkParser'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Activate &lt;a href="https://recommonmark.readthedocs.io/en/latest/auto_structify.html"&gt;AutoStructify&lt;/a&gt; component that enables the &lt;code&gt;eval_rs&lt;/code&gt; syntax to embed reStructuredText in markdown and syntax highlighting by adding the following configuration in conf.py.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;recommonmark.transform&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AutoStructify&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_config_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'recommonmark_config'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;'auto_toc_tree_section'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Contents'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AutoStructify&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install &lt;a href="https://github.com/ryanfox/sphinx-markdown-tables"&gt;sphinx_markdown_tables&lt;/a&gt; as recommonmark by itself doesn't support markdown table syntax.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;sphinx-markdown-tables
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;conf.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;extensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s"&gt;'sphinx_markdown_tables'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Internationalization (Multilingualization)
&lt;/h4&gt;

&lt;p&gt;Sphinx has an internationalization feature (&lt;a href="http://www.sphinx-doc.org/ja/stable/intl.html"&gt;sphinx-intl&lt;/a&gt;) on top of gettext.&lt;/p&gt;

&lt;h5&gt;
  
  
  Installation
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;sphinx-intl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Usage
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Compile messages to translate from source code in pot files in {build dir}/gettext.&lt;/span&gt;
make gettext
&lt;span class="c"&gt;# Generate po files from pot files in {source dir}/locale.&lt;/span&gt;
sphinx-intl update &lt;span class="nt"&gt;-p&lt;/span&gt; build/gettext &lt;span class="nt"&gt;-l&lt;/span&gt; en

&lt;span class="c"&gt;# Edit the generated po files.&lt;/span&gt;

&lt;span class="c"&gt;# Specify a language and generate translated documents. &lt;/span&gt;
make &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;SPHINXOPTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-D language='en'"&lt;/span&gt; html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you update the document, you can update po files in the same way.&lt;/p&gt;

&lt;h5&gt;
  
  
  Edit a PO file
&lt;/h5&gt;

&lt;p&gt;&lt;a href="https://poedit.net/"&gt;PoEdit&lt;/a&gt; is a easy-to-use editor though its complementary version has several feature limitations.&lt;/p&gt;

&lt;h5&gt;
  
  
  Reference
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://conyac.cc/ja/business/columns/localization_guide_po_pot"&gt;https://conyac.cc/ja/business/columns/localization_guide_po_pot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  HTML Themes
&lt;/h4&gt;

&lt;p&gt;Various HTML themes can be found in &lt;a href="https://sphinx-themes.org/"&gt;sphinx-themes.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sphinx-rtd-theme.readthedocs.io/en/stable/"&gt;Read the Docs&lt;/a&gt; theme seems to be popular among sphinx users.&lt;/p&gt;

&lt;h4&gt;
  
  
  Docker Image
&lt;/h4&gt;

&lt;p&gt;There are several images in DockerHub which set up sphinx, but none of them seems to be maintained well. Therefore I chose to build my own image from python official image (alpine).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://hub.docker.com/r/hnakamur/sphinx/"&gt;hnakamur/sphinx&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;The version of installed sphinx is still 2.0.1 (latest version is 2.1.2.).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hub.docker.com/r/suttang/sphinx-rtd-theme"&gt;docker-sphinx-rtd-theme&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;You can use the latest sphinx as its version is not specified in Dockerfile.&lt;/li&gt;
&lt;li&gt;Python is a little old (3.6), and sphinx-intl is not installed.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.toplaindocs/docker-sphinx"&gt;plaindocs/docker-sphinx&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Pushed once 4 years ago. Its image size is relatively large as it is based on Ubuntu.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Known Issues
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;The markdown list syntax &lt;code&gt;* item&lt;/code&gt; is converted into &lt;code&gt;&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;item&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;/code&gt;, resulting in generating additional p element and causing styling problems in some HTML templates.&lt;/li&gt;
&lt;li&gt;Inline styles will be deleted when converting into po files, and they need to be added manually in reST syntax.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tips
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Avoid Warnings on toctree
&lt;/h4&gt;

&lt;p&gt;Sphinx generates a warning when it finds a document which is not included in any toctree.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;checking consistency... C:\Users\xxx\Desktop\sx\source\test.md: WARNING: document isn't included in any toctree
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To suppress the warning, add &lt;a href="https://sphinx-users.jp/reverse-dict/system/orphan.html"&gt;orphan&lt;/a&gt; in the first line of the document.&lt;/p&gt;

&lt;h4&gt;
  
  
  Other Useful Packages
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Export documents in ePub format: &lt;code&gt;pip install Pillow&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Watch changes on documents and re-build automatically: &lt;code&gt;pip install sphinx-autobuild&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reference
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.sphinx-doc.org/ja/stable/contents.html"&gt;Official Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://qiita.com/pashango2/items/d1b379b699af85b529ce"&gt;https://qiita.com/pashango2/items/d1b379b699af85b529ce&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>sphinx</category>
      <category>markdown</category>
      <category>html</category>
    </item>
    <item>
      <title>Deploying a Web API on AWS Lambda: Difference between API Gateway and Application Load Balancer</title>
      <dc:creator>unhurried</dc:creator>
      <pubDate>Sat, 07 Sep 2019 23:25:43 +0000</pubDate>
      <link>https://dev.to/unhurried/deploying-a-web-api-on-aws-lambda-difference-between-api-gateway-and-application-load-balancer-3f55</link>
      <guid>https://dev.to/unhurried/deploying-a-web-api-on-aws-lambda-difference-between-api-gateway-and-application-load-balancer-3f55</guid>
      <description>&lt;p&gt;When we deploy a web API on AWS Lambda leveraging the benefit of server less architecture, we have two options for the front-end service for Lambda: API Gateway (API GW)  or Application Load Balancer (ALB). This articles studies the difference between them to help you to decide which to choose.&lt;/p&gt;

&lt;h5&gt;
  
  
  Features unique to API Gateway
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;It is obvious, but API Gateway specific features such as &lt;a href="https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-method-request-validation.html"&gt;Request Validation&lt;/a&gt;, &lt;a href="https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/mappings.html"&gt;Data Mapping&lt;/a&gt;, &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-control-access-to-api.html"&gt;Access Control&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-generate-sdk.html"&gt;SDK Generation&lt;/a&gt; cannot be used with ALB.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Protocols and Port Numbers
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;API GW supports only HTTPS (TLS 1.2) on 443 port. Note that though API GW supports &lt;a href="https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-private-apis.html"&gt;VPC Endpoint&lt;/a&gt;, you still need to use HTTPS in this case too.&lt;/li&gt;
&lt;li&gt;ALB supports both HTTP and HTTPS on arbitrary port numbers and TLS version also can be chosen from various &lt;a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies"&gt;options&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Request Timeout
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;API GW has a severe limitation of &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html#api-gateway-limits"&gt;29 seconds&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;ALB itself doesn't have a limitation, thus &lt;a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#prepare-lambda-function"&gt;the timeout of Lambda&lt;/a&gt; (up to 15 minutes) is applied.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Request and Response Sizes
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;API GW can handle up to 6MB payload, which is &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/limits.html"&gt;the ceiling of Lambda's payload size&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Note that 6MB includes headers and Base64-encoded body as payloads are requests and responses of Lambda.&lt;/li&gt;
&lt;li&gt;The limitation of API GW's payload size is &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html#api-gateway-limits"&gt;10MB&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;With ALB, the size of request and response bodies cannot be larger than 1MB. &lt;a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html#http-413-issues"&gt;413 error&lt;/a&gt; will be returned when a request body exceeds the limit, and &lt;a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html#http-502-issues"&gt;502 error&lt;/a&gt; for response body.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Request Event（&lt;a href="https://serverless-training.com/articles/api-gateway-vs-application-load-balancer-technical-details/#application-load-balancer-request-event-format-differences"&gt;Reference&lt;/a&gt;）
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;evt.headers (Request)

&lt;ul&gt;
&lt;li&gt;API GW sets header names and values with keeping the original upper and lower cases, whereas ALB decapitalize header names.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;evt.queryStringParameters (Request)

&lt;ul&gt;
&lt;li&gt;When there is no query string parameter, API GW sets &lt;code&gt;null&lt;/code&gt;, whereas ALB sets &lt;code&gt;{}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;API Gateway sets the URL decoded value for query string parameter key and value, whereas ALB sets them without URL decoding.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;evt.multiValueHeaders / evt.multiValueQueryStringParameters (Request)

&lt;ul&gt;
&lt;li&gt;API Gateway sets these parameters by default, whereas ALB requires that they are enabled in its configuration.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Response Event（&lt;a href="https://serverless-training.com/articles/api-gateway-vs-application-load-balancer-technical-details/#application-load-balancer-response-event-format-differences"&gt;Reference&lt;/a&gt;）
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt; ALB response event must include statusDescription, isBaseEncoded and headers (when "Multi Value Header" is enabled in ALB configuration).&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Cost
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Up to a certain request frequency, API GW is cheaper than ALB, that has a time-based charge. However for the services that receive a large amount of requests, ALB is more reasonable. (&lt;a href="https://serverless-training.com/articles/save-money-by-replacing-api-gateway-with-application-load-balancer/"&gt;Reference&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Other References
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/jp/blogs/networking-and-content-delivery/lambda-functions-as-targets-for-application-load-balancers/"&gt;Amazon Web Services Blog&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;It only mentions as follows:&lt;code&gt;there’s also a lot of overlap and commonality between the parameters used by Amazon API Gateway for triggering Lambda functions and ALB’s parameters.&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;a href="https://serverless-training.com/articles/api-gateway-vs-application-load-balancer-technical-details/"&gt;API Gateway vs Application Load Balancer—Technical Details&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.motidasystem.com/tech/aws/201901271852.html"&gt;API Gateway vs. ALB - 持田システム&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;It covers the difference in request timeout and limitation on response size.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
    </item>
    <item>
      <title>A Token Management Implementation for Web API Authentication in Java</title>
      <dc:creator>unhurried</dc:creator>
      <pubDate>Mon, 19 Aug 2019 21:54:20 +0000</pubDate>
      <link>https://dev.to/unhurried/a-token-management-implementation-for-web-api-authentication-in-java-4l25</link>
      <guid>https://dev.to/unhurried/a-token-management-implementation-for-web-api-authentication-in-java-4l25</guid>
      <description>&lt;p&gt;This article studies an implementation of a synchronized process in Java that enables multiple threads to share same timed tokens, assuming access tokens in OAuth2, for Web API authentication.&lt;/p&gt;

&lt;h4&gt;
  
  
  Specification of Token Management
&lt;/h4&gt;

&lt;p&gt;I assume the following specification for this token management system.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple threads call Web APIs with the same token.&lt;/li&gt;
&lt;li&gt;When a token expires, a thread that detects the expiration first will update the token.&lt;/li&gt;
&lt;li&gt;During the update process, token retrievals from other threads needs to wait the completion of the update.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  An Implementation in Java
&lt;/h4&gt;

&lt;p&gt;The following is an implementation of the token management system described above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TokenManager&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// Singleton Pattern&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;TokenManager&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TokenManager&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;TokenManager&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;TokenManager&lt;/span&gt; &lt;span class="nf"&gt;getInstance&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="cm"&gt;/* Set "volatile" to variables for token and update time so that any
     threads can retrieve the up-to-date state of the variables. */&lt;/span&gt;
  &lt;span class="c1"&gt;// Timed token&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;volatile&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// Update time calcurated from TTL of the token&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;refreshAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0L&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// getToken doesn't need "synchronized" as any threads can retrieve&lt;/span&gt;
  &lt;span class="c1"&gt;//  the up-to-date token with the aid of "volatile" keyword.&lt;/span&gt;
  &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getToken&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;refreshAt&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;syncUpdateToken&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Make the method "synchronized" so that only one thread can&lt;/span&gt;
  &lt;span class="c1"&gt;// execute it in time.&lt;/span&gt;
  &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;synchronized&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;syncUpdateToken&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Prevent subsequents threads that call getToken method during&lt;/span&gt;
    &lt;span class="c1"&gt;// the token update from updating the token again.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;refreshAt&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Token Update Process&lt;/span&gt;
    &lt;span class="c1"&gt;// Update "token" before "refreshAt" as "refreshAt" is used&lt;/span&gt;
    &lt;span class="c1"&gt;// first in getToken method to check the token expiration.&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;refreshAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By making instance variables (token and refreshAt) "volatile", getToken method doesn't need "synchronized", which enables parallel execution of token retrievals while the token is valid.&lt;/p&gt;

&lt;p&gt;Note that results in subsequent threads invoking updateToken method, thus token expiration check is also needed in updateToken to prevent unnecessary token updates.&lt;/p&gt;

</description>
      <category>java</category>
    </item>
  </channel>
</rss>
