<?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: prakash chokalingam</title>
    <description>The latest articles on DEV Community by prakash chokalingam (@prakash_chokalingam).</description>
    <link>https://dev.to/prakash_chokalingam</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%2F114900%2Fa60e8ca2-7d75-41da-b8b0-788938bc93fc.jpg</url>
      <title>DEV Community: prakash chokalingam</title>
      <link>https://dev.to/prakash_chokalingam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/prakash_chokalingam"/>
    <language>en</language>
    <item>
      <title>Set up MongoDB primary and secondary with Docker.</title>
      <dc:creator>prakash chokalingam</dc:creator>
      <pubDate>Sun, 05 Jan 2025 19:10:33 +0000</pubDate>
      <link>https://dev.to/prakash_chokalingam/set-up-mongodb-primary-and-secondary-with-docker-7gn</link>
      <guid>https://dev.to/prakash_chokalingam/set-up-mongodb-primary-and-secondary-with-docker-7gn</guid>
      <description>&lt;p&gt;MongoDB is a popular choice for developers today when it comes to NoSQL databases. The MongoDB Community Edition is readily available as a Docker image.&lt;/p&gt;

&lt;p&gt;To enable MongoDB transactional queries, you need to configure a replica set with primary and secondary database connections. &lt;/p&gt;

&lt;p&gt;In this post, we’ll walk through how to set up MongoDB’s primary and secondary nodes and configure a replica set using a single docker-compose file.&lt;/p&gt;

&lt;h4&gt;
  
  
  Prerequisites for Running the Below docker-compose File
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Create a Docker Network
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; docker network create dev_network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Replica Set Configuration Script&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create a file named &lt;code&gt;replicaset.sh&lt;/code&gt; under the &lt;code&gt;scripts&lt;/code&gt; directory to configure the replica set:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;scripts/replicaset.sh&lt;/code&gt;&lt;/p&gt;


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



&lt;ul&gt;
&lt;li&gt;Grant Permissions to the Script
Ensure the script has execute permissions so Docker can access it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nb"&gt;chmod&lt;/span&gt; +x scripts/replicaset.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Update the Host File for Resolvers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Map the Mongo paths to &lt;code&gt;localhost&lt;/code&gt; by editing the &lt;code&gt;/etc/hosts&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;127.0.0.1   primary secondary1 secondary2 &lt;span class="c"&gt;# mongo docker resolvers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Create the Docker Compose File&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Define your MongoDB configuration in a docker-compose.yml file:&lt;/p&gt;


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



&lt;ul&gt;
&lt;li&gt;Run the Docker Compose File
Start the containers using the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🎉 That’s it! Your MongoDB primary and secondaries are up and running. The replica set is configured and ready to use.&lt;/p&gt;

&lt;p&gt;Your MongoDB connection URL is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mongodb://localhost:27020,localhost:27021,localhost:27022/dbname?replicaSet=rs0&amp;amp;retryWrites=true&amp;amp;w=majority&lt;/code&gt;&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>docker</category>
      <category>secondarydb</category>
      <category>transactional</category>
    </item>
    <item>
      <title>Spin a Framework-Free HTTP Router Server in Go 1.22 With Ease</title>
      <dc:creator>prakash chokalingam</dc:creator>
      <pubDate>Thu, 15 Feb 2024 10:20:19 +0000</pubDate>
      <link>https://dev.to/prakash_chokalingam/spin-a-framework-free-http-router-server-in-go-122-with-ease-6nc</link>
      <guid>https://dev.to/prakash_chokalingam/spin-a-framework-free-http-router-server-in-go-122-with-ease-6nc</guid>
      <description>&lt;p&gt;Transitioning from Node.js or Python development, you're likely familiar with the convenience of frameworks like Express or Flask for spinning up HTTP servers with rich routing capabilities. Similarly, in the Go ecosystem, frameworks such as Gin and Gorilla/Mux have been the go-to solutions for developers seeking to implement efficient routing within their applications.&lt;/p&gt;

&lt;p&gt;However, the landscape has evolved with the release of Go 1.22. The net/http package, a staple for network-related operations in Go, has received significant enhancements, particularly in its routing capabilities. This evolution means that developers can now implement complex HTTP servers without relying on external frameworks, streamlining the development process and reducing dependency overhead.&lt;/p&gt;

&lt;p&gt;Here's how to build a simple todo application using the net/http server mux.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewServeMux&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"POST /todos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"create a todo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET /todos"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"get all todos"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PATCH /todos/{id}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PathValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"update a todo by id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DELETE /todos/{id}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PathValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"delete a todo by id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;router&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;You can also create a route that matches exactly or uses a wildcard for flexible matching.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// wild card&lt;/span&gt;
&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PATCH /todos/{rest...}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PathValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"rest"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wild card route"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c"&gt;// exact match&lt;/span&gt;
&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/todos/{$}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"exact match"&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;For more details deep dive into the official go documentation &lt;a href="https://pkg.go.dev/net/http#ServeMux"&gt;https://pkg.go.dev/net/http#ServeMux&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>codebytes</category>
      <category>go</category>
      <category>router</category>
      <category>http</category>
    </item>
    <item>
      <title>Seamlessly Embed Files Into Your Go Binary</title>
      <dc:creator>prakash chokalingam</dc:creator>
      <pubDate>Fri, 02 Feb 2024 08:07:28 +0000</pubDate>
      <link>https://dev.to/prakash_chokalingam/seamlessly-embed-files-into-your-go-binary-4ie2</link>
      <guid>https://dev.to/prakash_chokalingam/seamlessly-embed-files-into-your-go-binary-4ie2</guid>
      <description>&lt;p&gt;Incorporating YAML, JSON, or other configuration files into your Go application is becoming a standard practice, these files are often being referenced by file paths within the project. Although the go-build process completes smoothly, executing the standalone binary can result in a 'file not found' error. This means you have to keep these setting files close to your app wherever you run it.&lt;/p&gt;

&lt;p&gt;To circumvent this issue, Go offers a powerful feature known as &lt;strong&gt;embed&lt;/strong&gt;. This allows developers to include their files directly within the binary by creating an embedded file system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"embed"&lt;/span&gt;

&lt;span class="c"&gt;//go:embed config.yaml&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;embedFS&lt;/span&gt; &lt;span class="n"&gt;embed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FS&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;
&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;embedFS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"config.yaml"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can even embed a list of directories as part of your go binary,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"embed"&lt;/span&gt;

&lt;span class="c"&gt;//go:embed templates/* config/*&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;embedFS&lt;/span&gt; &lt;span class="n"&gt;embed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FS&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;
&lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;embedFS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"templates/email.hbs"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This feature enables you to run the go binary standalone without any external dependencies.&lt;/p&gt;

&lt;p&gt;For more details please check the &lt;a href="https://pkg.go.dev/embed"&gt;go embed documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>codebytes</category>
      <category>go</category>
      <category>embedfs</category>
      <category>build</category>
    </item>
    <item>
      <title>Envoy External Authorization with Golang GRPC service</title>
      <dc:creator>prakash chokalingam</dc:creator>
      <pubDate>Wed, 21 Jun 2023 12:10:11 +0000</pubDate>
      <link>https://dev.to/prakash_chokalingam/envoy-external-authorization-with-golang-grpc-service-58h8</link>
      <guid>https://dev.to/prakash_chokalingam/envoy-external-authorization-with-golang-grpc-service-58h8</guid>
      <description>&lt;p&gt;&lt;a href="https://www.envoyproxy.io" rel="noopener noreferrer"&gt;Envoy&lt;/a&gt; is a cloud native opensource proxy server. The Envoy proxy offers a variety of http filters to handle incoming requests.&lt;/p&gt;

&lt;p&gt;Out of them &lt;a href="https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/ext_authz_filter" rel="noopener noreferrer"&gt;External authorisation&lt;/a&gt; is a filter type that directs an incoming request to an external service and waits for its authorisation to continue the request.The external service, which has the ability to modify or suspend the incoming request, can be either a grpc_service or a http_service.&lt;/p&gt;

&lt;p&gt;Working example: &lt;a href="https://github.com/prakashchokalingam/envoy_ext_auth_grpc_go" rel="noopener noreferrer"&gt;prakashchokalingam/envoy_ext_auth_grpc_go&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek8vgpnh3mystitusajs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fek8vgpnh3mystitusajs.png" alt="envoy filter to go flow diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's look at connecting a GRPC-based Golang service using the Envoy external auth filter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a golang grpc based server:
&lt;/h3&gt;

&lt;h6&gt;
  
  
  main.go
&lt;/h6&gt;

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

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"fmt"&lt;/span&gt;
  &lt;span class="s"&gt;"net"&lt;/span&gt;
  &lt;span class="s"&gt;"google.golang.org/grpc"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;endPoint&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost:%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endPoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;grpcServer&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;grpcServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listen&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;
  
  
  Extend with go-control-plane protobuf
&lt;/h3&gt;

&lt;p&gt;The above server should be extended and registered with the envoyproxy go-control-plane protobuf server with a check function defined struct.&lt;/p&gt;
&lt;h6&gt;
  
  
  main.go
&lt;/h6&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"fmt"&lt;/span&gt;
  &lt;span class="s"&gt;"net"&lt;/span&gt;

   &lt;span class="n"&gt;auth_pb&lt;/span&gt; &lt;span class="s"&gt;"github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"&lt;/span&gt;
  &lt;span class="s"&gt;"google.golang.org/grpc"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// struct with check method&lt;/span&gt;
  &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;AuthServer&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;AuthServer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;auth_pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckRequest&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;auth_pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"All request goes through me"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// block if path is /private&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Attributes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;not&lt;/span&gt; &lt;span class="n"&gt;allowed&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// allow all other requests&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;auth_pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckResponse&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;


  &lt;span class="n"&gt;endPoint&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost:%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;endPoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;grpcServer&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;grpc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c"&gt;// register envoy proto server&lt;/span&gt;
  &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;AuthServer&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="n"&gt;auth_pb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterAuthorizationServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grpcServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;grpcServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listen&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;If nil is returned in the check method rather than &amp;amp;auth_pb.CheckResponse, the request will be suspended with a 403 error code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Envoy will also return 403 if the service is offline or unreachable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Last but not least, set up your Envoy
&lt;/h3&gt;

&lt;p&gt;In your envoy config add the filter &lt;code&gt;envoy.filters.http.ext_authz&lt;/code&gt;and point it to the Go service cluster&lt;/p&gt;
&lt;h6&gt;
  
  
  envoy.yml
&lt;/h6&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;static_resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;listeners&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;listener_0&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;socket_address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;0.0.0.0&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;port_value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;80&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;filter_chains&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;envoy.filters.network.http_connection_manager&lt;/span&gt;
              &lt;span class="na"&gt;typed_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@type"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager&lt;/span&gt;
                &lt;span class="s"&gt;codec_type&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;auto&lt;/span&gt;
                &lt;span class="s"&gt;stat_prefix&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ingress_http&lt;/span&gt;
                &lt;span class="s"&gt;route_config&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local_route&lt;/span&gt;
                  &lt;span class="na"&gt;virtual_hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                   &lt;span class="s"&gt;...&lt;/span&gt;
                &lt;span class="na"&gt;http_filters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;envoy.filters.http.ext_authz&lt;/span&gt;
                    &lt;span class="na"&gt;typed_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                      &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@type"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz&lt;/span&gt;
                      &lt;span class="s"&gt;transport_api_version&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v3&lt;/span&gt;
                      &lt;span class="s"&gt;grpc_service&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
                        &lt;span class="na"&gt;envoy_grpc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                          &lt;span class="na"&gt;cluster_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go_grpc_cluster&lt;/span&gt;
                      &lt;span class="na"&gt;include_peer_certificate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
                        &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="na"&gt;clusters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go_grpc_cluster&lt;/span&gt;
      &lt;span class="na"&gt;connect_timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.25s&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LOGICAL_DNS&lt;/span&gt;
      &lt;span class="na"&gt;typed_extension_protocol_options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;envoy.extensions.upstreams.http.v3.HttpProtocolOptions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@type"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions&lt;/span&gt;
          &lt;span class="s"&gt;explicit_http_config&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;http2_protocol_options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
      &lt;span class="na"&gt;load_assignment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;cluster_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;go_grpc_cluster&lt;/span&gt;
        &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;lb_endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;socket_address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;127.0.0.1&lt;/span&gt;
                  &lt;span class="na"&gt;port_value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3001&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;To see an example snippet for customising headers, &lt;a href="https://github.com/prakashchokalingam/envoy_ext_auth_grpc_go/blob/main/clusters/go_grpc_filter/main.go#L34" rel="noopener noreferrer"&gt;click here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out this repository for a fully functional code sample&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/prakashchokalingam" rel="noopener noreferrer"&gt;
        prakashchokalingam
      &lt;/a&gt; / &lt;a href="https://github.com/prakashchokalingam/envoy_ext_auth_grpc_go" rel="noopener noreferrer"&gt;
        envoy_ext_auth_grpc_go
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Working example of envoy external auth filter with go lang grpc service
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;a rel="noopener noreferrer" href="https://private-user-images.githubusercontent.com/5512765/247538270-5b00ad6b-4896-4b90-82fa-936b0ec0d6bc.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjgwNjgzMTAsIm5iZiI6MTcyODA2ODAxMCwicGF0aCI6Ii81NTEyNzY1LzI0NzUzODI3MC01YjAwYWQ2Yi00ODk2LTRiOTAtODJmYS05MzZiMGVjMGQ2YmMucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MTAwNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDEwMDRUMTg1MzMwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9YzRkZWIwMGY2YWIyMjlmNWFmOTc2NWU5NmQ3N2E0NThlNWIwYzIwNzU0ZjYzYjE1ZWFhNmYwMDJjNDgzMmE5ZSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.fxtt8mmsETWnp-X3_F-aMiLSOcS_BQpP2IKA7mzRj7w"&gt;&lt;img width="685" alt="Screenshot 2023-06-20 at 10 16 03 PM" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fprivate-user-images.githubusercontent.com%2F5512765%2F247538270-5b00ad6b-4896-4b90-82fa-936b0ec0d6bc.png%3Fjwt%3DeyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjgwNjgzMTAsIm5iZiI6MTcyODA2ODAxMCwicGF0aCI6Ii81NTEyNzY1LzI0NzUzODI3MC01YjAwYWQ2Yi00ODk2LTRiOTAtODJmYS05MzZiMGVjMGQ2YmMucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI0MTAwNCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNDEwMDRUMTg1MzMwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9YzRkZWIwMGY2YWIyMjlmNWFmOTc2NWU5NmQ3N2E0NThlNWIwYzIwNzU0ZjYzYjE1ZWFhNmYwMDJjNDgzMmE5ZSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.fxtt8mmsETWnp-X3_F-aMiLSOcS_BQpP2IKA7mzRj7w"&gt;&lt;/a&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Example repo to demonstrate Envoy External Authorization with Golang GRPC service&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;This repository provides an &lt;a href="https://github.com/prakashchokalingam/envoy_ext_auth_grpc_go/blob/main/envoy.yml" rel="noopener noreferrer"&gt;envoy configuration&lt;/a&gt; file with an external auth filter activated for all incoming routes at port 8080&lt;/p&gt;

&lt;p&gt;The envoy is configured with two clusters,&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;&lt;a href="https://github.com/prakashchokalingam/envoy_ext_auth_grpc_go/tree/main/clusters/go_grpc_filter" rel="noopener noreferrer"&gt;go_grpc_filter&lt;/a&gt;&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;The filter &lt;code&gt;envoy.filters.http.ext_authz&lt;/code&gt; in envoy is pointed at this go grpc cluster. All incoming requests will be forwarded to this cluster.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/prakashchokalingam/envoy_ext_auth_grpc_go/blob/main/clusters/go_grpc_filter/main.go#L15" rel="noopener noreferrer"&gt;Check method&lt;/a&gt; will be called during a request; it then adds a custom header to all other requests and rejects requests with the path '/private'.&lt;/p&gt;

&lt;p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;br&gt;
&lt;thead&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;th&gt;Request&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;grpc_filter&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;status&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;http_server_response&lt;/th&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/thead&gt;
&lt;br&gt;
&lt;tbody&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;/&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;x-custom-header = "Hello World"&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;Hello World&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;/ private&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/tbody&gt;
&lt;br&gt;
&lt;/table&gt;&lt;/div&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;&lt;a href="https://github.com/prakashchokalingam/envoy_ext_auth_grpc_go/tree/main/clusters/go_simple_http" rel="noopener noreferrer"&gt;go_simple_http&lt;/a&gt;&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;It is a straightforward Golang HTTP server that merely emits the custom header value &lt;code&gt;x-custom-header&lt;/code&gt; added via the go_grpc_filter cluster.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;To run this example&lt;/h1&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Start the envoy server&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;envoy -c envoy.yml&lt;/pre&gt;

&lt;/div&gt;

&lt;ol start="2"&gt;
&lt;li&gt;start the go_grpc_filter &amp;amp; go_simple_http servers by navigating to the cluster root.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;go run main.go&lt;/pre&gt;

&lt;/div&gt;


&lt;ol start="3"&gt;&lt;li&gt;…&lt;/li&gt;&lt;/ol&gt;
&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/prakashchokalingam/envoy_ext_auth_grpc_go" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>envoy</category>
      <category>go</category>
      <category>grpc</category>
      <category>istio</category>
    </item>
    <item>
      <title>Codebytes: REPL it with NestJs</title>
      <dc:creator>prakash chokalingam</dc:creator>
      <pubDate>Tue, 29 Nov 2022 19:17:02 +0000</pubDate>
      <link>https://dev.to/prakash_chokalingam/codebytes-repl-it-with-nestjs-1iae</link>
      <guid>https://dev.to/prakash_chokalingam/codebytes-repl-it-with-nestjs-1iae</guid>
      <description>&lt;p&gt;I am a big fan of byebug, a powerful ruby debugger, and I was thrilled to know about the REPL server in the &lt;a href="https://trilon.io/blog/nestjs-9-is-now-available" rel="noopener noreferrer"&gt;NestJS V9 release notes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6cy0z38ygxw2nqjhlwz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6cy0z38ygxw2nqjhlwz.png" alt="debug infograph" width="512" height="512"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.flaticon.com/free-icons/debug" rel="noopener noreferrer"&gt;source: manshagraphics-Flaticon&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The REPL server acts as a debugger for NestJS by launching an interactive server with all of the context required for your nest app. So you can basically interact with all of your methods directly.&lt;/p&gt;

&lt;p&gt;To start the REPL server in your NestJS app,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Make a REPL entry file called &lt;code&gt;repl.ts&lt;/code&gt; alongside &lt;code&gt;main.ts&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Include your app module to the repl method in the &lt;code&gt;repl.ts&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// repl.ts&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;repl&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;@nestjs/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppModule&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;./app.module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;repl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppModule&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Launch your repl server using the below command,
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run start &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--entryFile&lt;/span&gt; repl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It will initiate an interactive node server, from which you can easily access your nest app methods by getting them,&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="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppService&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;sayHelloWorld&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhq5o1g6q9j08umzeg6z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhq5o1g6q9j08umzeg6z.png" alt="repl server exec screenshot" width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/embed/nestjs-repl-q1vgot?expanddevtools=1&amp;amp;fontsize=14&amp;amp;hidenavigation=1&amp;amp;module=%2Fsrc%2Frepl.ts&amp;amp;theme=dark" rel="noopener noreferrer"&gt;play with REPL on codesandbox&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;for more usage methods on REPL click here to read the &lt;a href="https://docs.nestjs.com/recipes/repl" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>codebytes</category>
      <category>nestjs</category>
      <category>repl</category>
      <category>node</category>
    </item>
    <item>
      <title>Introduction to a stateful &amp; maintainable React Local Storage hook</title>
      <dc:creator>prakash chokalingam</dc:creator>
      <pubDate>Thu, 30 Dec 2021 07:09:13 +0000</pubDate>
      <link>https://dev.to/prakash_chokalingam/introduction-to-a-stateful-maintainable-react-local-storage-hook-31ie</link>
      <guid>https://dev.to/prakash_chokalingam/introduction-to-a-stateful-maintainable-react-local-storage-hook-31ie</guid>
      <description>&lt;p&gt;When it comes to storing a value on the client-side persistently, most of us will prefer browser storage (local or session storage) because of its simplified APIs to store and retrieve data. &lt;/p&gt;

&lt;p&gt;Yet maintaining these storages in large-scale applications are not so easy, especially with micro frontends architecture.&lt;/p&gt;

&lt;p&gt;The hook &lt;a href="https://www.npmjs.com/package/@webcored/react-local-storage" rel="noopener noreferrer"&gt;&lt;strong&gt;@webcored/react-local-storage&lt;/strong&gt;&lt;/a&gt; provides an awesome set of features to maintain the browser storage effortlessly for the long run.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Namespacing &amp;amp; Configurations&lt;/li&gt;
&lt;li&gt;Defaults &amp;amp; States&lt;/li&gt;
&lt;li&gt;Versions &amp;amp; Migrations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Namespacing &amp;amp; Configurations &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Unless it's documented, we don't know the storage keys being used in an application &amp;amp; we are not sure about the values of the keys as well.&lt;/p&gt;

&lt;p&gt;Key name conflicts are more common in micro-frontends. An app should control its own set of keys and it should not override the common or other app's key. Hence, namespacing plays a major factor to avoid these conflicts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff25oj8undch2lzidxpjw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff25oj8undch2lzidxpjw.gif" alt="conflict"&gt;&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;storageConfig&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="s2"&gt;@webcored/react-local-storage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;storageConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;delimiter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If the key is &lt;code&gt;user&lt;/code&gt;, the storage key name is &lt;code&gt;dev#user&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  other available storage configurations,
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;storage: choose between local or session storage&lt;/li&gt;
&lt;li&gt;storages: key configurations&lt;/li&gt;
&lt;li&gt;react: instance for state management (useState hook)
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;user&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;./storages/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;storageConfig&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="s2"&gt;@webcored/react-local-storage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;storageConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;delimiter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;storages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="c1"&gt;// user key configs&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="nx"&gt;react&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;
  
  
  Defaults &amp;amp; States &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The default state for keys in browser storage is the most required feature. It indulges a lot of programming effort to maintain the default state for every key.&lt;/p&gt;

&lt;p&gt;In @webcored/react-local-storage each key can have its config, and the default states for keys can be incorporated easily.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;/storages/user.js&lt;/small&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;storageKeyConfig&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="s2"&gt;@webcored/react-local-storage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;storageKeyConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Guest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guest@email.com&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The storages are simply accessible via the &lt;code&gt;useLocalStorage&lt;/code&gt; hook in a stateful way.&lt;/p&gt;

&lt;p&gt;&lt;small&gt;/component.js&lt;/small&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useLocalStorage&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="s2"&gt;@webcored/react-local-storage&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userStorage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLocalStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And the dispatcher comes with painless APIs to invoke the storage programmatically.&lt;/p&gt;
&lt;h4&gt;
  
  
  update
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;userStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;avatar.jpg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  reset
&lt;/h4&gt;

&lt;p&gt;Reset the storage to the default state.&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="nx"&gt;userStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reset&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  remove
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;userStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Versions &amp;amp; Migrations &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

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

&lt;p&gt;Since the storages are persistent, changing its data structure quite often may be challenging, and it involves a lot of code changes per key. With @webcored/react-local-storage these data migrations can be simply handled with a version number &amp;amp; a migration callback in the key config.&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;storageKeyConfig&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="s2"&gt;@webcored/react-local-storage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;storageKeyConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Guest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guest@email.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;avatar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guest.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// new&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;migration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;defaultValue&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;defaultValue&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;p&gt;@webcored/react-local-storage supports versioning of keys by default. &lt;br&gt;
As per the above code block, the current version of user storage is incremented. While rendering, if the browser had an outdated version of storage, the migration method will be invoked. The migrated value will be considered as the latest version.&lt;/p&gt;
&lt;h4&gt;
  
  
  other highlights
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;supports all data types&lt;/li&gt;
&lt;li&gt;typescript supported&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  checkout the sample apps
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/webcored/react-local-storage-app-js" rel="noopener noreferrer"&gt;javascript&lt;/a&gt; | &lt;a href="https://github.com/webcored/react-local-storage-app-ts" rel="noopener noreferrer"&gt;typescript&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you like, Promote the lib with a star ⭐️ &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/webcored" rel="noopener noreferrer"&gt;
        webcored
      &lt;/a&gt; / &lt;a href="https://github.com/webcored/react-local-storage" rel="noopener noreferrer"&gt;
        react-local-storage
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A stateful react hook for browser storage
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/3ba95ba10655fb49b8a8bcf55b755885c8692e278b31cf94bf4e893073bbc41c/68747470733a2f2f776562636f7265642d6173736574732e6e65746c6966792e6170702f72656163742d6c6f63616c2d73746f726167652e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/3ba95ba10655fb49b8a8bcf55b755885c8692e278b31cf94bf4e893073bbc41c/68747470733a2f2f776562636f7265642d6173736574732e6e65746c6966792e6170702f72656163742d6c6f63616c2d73746f726167652e706e67" height="250px"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;React Local Storage&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;A stateful react hook for browser storage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/webcored/react-local-storage/actions/workflows/build.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/webcored/react-local-storage/actions/workflows/build.yml/badge.svg?branch=main" alt="build"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/@webcored/react-local-storage" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/77927e51beeb572e21c0d5ff765d752bf060cac4c726561571d5c0cf2f9f87de/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f40776562636f7265642f72656163742d6c6f63616c2d73746f726167653f636f6c6f723d2532333935394441" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/@webcored/react-local-storage" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e0638419db013c6d8192346860f98df5b1b747ee743fd20a93e4c6dca85a6265/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f40776562636f7265642f72656163742d6c6f63616c2d73746f726167653f636f6c6f723d2532333935394441" alt="downloads"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/6d2928d3dca94c9bffc597dd201ef2cc2791b0a2eb38a47634e8309f97038b47/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f74797065732f74797065736372697074"&gt;&lt;img src="https://camo.githubusercontent.com/6d2928d3dca94c9bffc597dd201ef2cc2791b0a2eb38a47634e8309f97038b47/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f74797065732f74797065736372697074" alt="typescript"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/d3afb1208662c936fafd7f3904980f038d6efc3f42f83705a5c7729e5b50b62e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f6e747269627574696f6e732d77656c636f6d652d253343434f4c4f522533452e7376673f7374796c653d666c6174"&gt;&lt;img src="https://camo.githubusercontent.com/d3afb1208662c936fafd7f3904980f038d6efc3f42f83705a5c7729e5b50b62e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f6e747269627574696f6e732d77656c636f6d652d253343434f4c4f522533452e7376673f7374796c653d666c6174" alt="contributions"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why?&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/webcored/react-local-storage#configurations" rel="noopener noreferrer"&gt;Configurable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webcored/react-local-storage#defaults" rel="noopener noreferrer"&gt;Defaults support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/webcored/react-local-storage#versions--migrations" rel="noopener noreferrer"&gt;Versions &amp;amp; Migrations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;npm install @webcored/react-local-storage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;component.jsx&lt;/p&gt;
&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;useLocalStorage&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"@webcored/react-local-storage"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s1"&gt;user&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-s1"&gt;userStorage&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;useLocalStorage&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'user'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

...&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
typescript


&lt;div class="highlight highlight-source-ts notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-s1"&gt;user&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-s1"&gt;userStorage&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;useLocalStorage&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pl-smi"&gt;User&lt;/span&gt;&lt;span class="pl-kos"&gt;&amp;gt;&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;'user'&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
  
...&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;div class="markdown-heading"&gt;
&lt;h5 class="heading-element"&gt;update&lt;/h5&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-s1"&gt;userStorage&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;update&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt; ...&lt;span class="pl-s1"&gt;user&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-c1"&gt;name&lt;/span&gt;: &lt;span class="pl-s"&gt;'new name'&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h5 class="heading-element"&gt;remove&lt;/h5&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-s1"&gt;userStorage&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;remove&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h5 class="heading-element"&gt;reset&lt;/h5&gt;

&lt;/div&gt;

&lt;p&gt;Reset's to the default value provided in the &lt;a href="https://github.com/webcored/react-local-storage#defaults" rel="noopener noreferrer"&gt;key config&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-s1"&gt;userStorage&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-en"&gt;reset&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Sample app&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;br&gt;
&lt;thead&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;th&gt;&lt;a href="https://github.com/webcored/react-local-storage-app-js" rel="noopener noreferrer"&gt;View on Github&lt;/a&gt;&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;&lt;a href="https://codesandbox.io/s/react-local-storage-js-di7we" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/ecd139ba9847d0c77607c86339eb8ee6939ca85143a92ae16ebf20f58325e1b6/68747470733a2f2f636f646573616e64626f782e696f2f7374617469632f696d672f706c61792d636f646573616e64626f782e737667"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/thead&gt;
&lt;br&gt;
&lt;/table&gt;&lt;/div&gt;&lt;/p&gt;

typescript

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;a href="https://github.com/webcored/react-local-storage-app-ts" rel="noopener noreferrer"&gt;View on Github&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://codesandbox.io/s/react-local-storage-ts-gmmiy" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/ecd139ba9847d0c77607c86339eb8ee6939ca85143a92ae16ebf20f58325e1b6/68747470733a2f2f636f646573616e64626f782e696f2f7374617469632f696d672f706c61792d636f646573616e64626f782e737667"&gt;&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Configurations&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-v"&gt;React&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;'react'&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;user&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;'./storages/user'&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;storageConfig&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"@webcored/react-local-storage"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-en"&gt;storageConfig&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;namespace&lt;/span&gt;: &lt;span class="pl-s"&gt;'app'&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;delimiter&lt;/span&gt;: &lt;span class="pl-s"&gt;'/'&lt;/span&gt;
  &lt;span class="pl-s1"&gt;react&lt;/span&gt;: &lt;span class="pl-v"&gt;React&lt;/span&gt;
  &lt;span class="pl-s1"&gt;storages&lt;/span&gt;: &lt;span class="pl-kos"&gt;{&lt;/span&gt;
    user
  &lt;span class="pl-kos"&gt;}&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/webcored/react-local-storage" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>reactlocalstorage</category>
      <category>react</category>
      <category>reacthooks</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Codebytes: Shorter UUIDs with collision prediction using nanoid</title>
      <dc:creator>prakash chokalingam</dc:creator>
      <pubDate>Fri, 15 Oct 2021 15:33:12 +0000</pubDate>
      <link>https://dev.to/prakash_chokalingam/codebytes-shorter-uuids-with-collision-prediction-using-nanoid-co8</link>
      <guid>https://dev.to/prakash_chokalingam/codebytes-shorter-uuids-with-collision-prediction-using-nanoid-co8</guid>
      <description>&lt;p&gt;To generate an unique ID most of us use npm libraries and node utils like uuid, crypto.randomUUID. One of the major cons is these IDs are larger in size and the shorter UUID generation will increase the &lt;strong&gt;probability of duplicate&lt;/strong&gt; IDs.&lt;/p&gt;

&lt;p&gt;Here comes the saviour, &lt;a href="https://github.com/ai/nanoid" rel="noopener noreferrer"&gt;nanoid&lt;/a&gt; - A tiny, secure, URL-friendly, unique string ID generator for JavaScript.&lt;/p&gt;

&lt;p&gt;Since the bigger alphabet is being used in the UUID generation, nanoid can generate random unique ids within 21 chars.&lt;/p&gt;

&lt;p&gt;And its 2x faster and safer than other UUID generators.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wait... This will blow your mind!
&lt;/h3&gt;

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

&lt;p&gt;Nanoid is completely configurable from size to char's, to be used while generating the UUIDs. Then how does it &lt;strong&gt;avoid the probability of duplication?&lt;/strong&gt; It comes with a &lt;strong&gt;&lt;a href="https://zelark.github.io/nano-id-cc/" rel="noopener noreferrer"&gt;collision calculator&lt;/a&gt;&lt;/strong&gt; which helps to predict the probability of collision based on configuration.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fedocpgy3z19r122axngu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fedocpgy3z19r122axngu.png" alt="collision calculator"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It has support for various other programming languages. Checkout this awesome repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ai" rel="noopener noreferrer"&gt;
        ai
      &lt;/a&gt; / &lt;a href="https://github.com/ai/nanoid" rel="noopener noreferrer"&gt;
        nanoid
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A tiny (124 bytes), secure, URL-friendly, unique string ID generator for JavaScript
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Nano ID&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/a477af76393072f91113471d2d536cbd402586e94cbcce617154953cb0e11500/68747470733a2f2f61692e6769746875622e696f2f6e616e6f69642f6c6f676f2e737667"&gt;&lt;img src="https://camo.githubusercontent.com/a477af76393072f91113471d2d536cbd402586e94cbcce617154953cb0e11500/68747470733a2f2f61692e6769746875622e696f2f6e616e6f69642f6c6f676f2e737667" alt="Nano ID logo by Anton Lovchikov" width="180" height="94"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;English&lt;/strong&gt; | &lt;a href="https://github.com/ai/nanoid./README.ru.md" rel="noopener noreferrer"&gt;Русский&lt;/a&gt; | &lt;a href="https://github.com/ai/nanoid./README.zh-CN.md" rel="noopener noreferrer"&gt;简体中文&lt;/a&gt; | &lt;a href="https://github.com/ai/nanoid./README.id-ID.md" rel="noopener noreferrer"&gt;Bahasa Indonesia&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A tiny, secure, URL-friendly, unique string ID generator for JavaScript.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“An amazing level of senseless perfectionism
which is simply impossible not to respect.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Small.&lt;/strong&gt; 116 bytes (minified and brotlied). No dependencies
&lt;a href="https://github.com/ai/size-limit" rel="noopener noreferrer"&gt;Size Limit&lt;/a&gt; controls the size.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safe.&lt;/strong&gt; It uses hardware random generator. Can be used in clusters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Short IDs.&lt;/strong&gt; It uses a larger alphabet than UUID (&lt;code&gt;A-Za-z0-9_-&lt;/code&gt;).
So ID size was reduced from 36 to 21 symbols.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portable.&lt;/strong&gt; Nano ID was ported
to over &lt;a href="https://github.com/ai/nanoid./README.md#other-programming-languages" rel="noopener noreferrer"&gt;20 programming languages&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight highlight-source-js notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;nanoid&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;'nanoid'&lt;/span&gt;
&lt;span class="pl-s1"&gt;model&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;id&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;nanoid&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c"&gt;//=&amp;gt; "V1StGXR8_Z5jdHi6B-myT"&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/950a0a20abf52af1b9e961d13bf35410771a0f21f11a5004a2997a110b22506b/68747470733a2f2f63646e2e6576696c6d61727469616e732e636f6d2f6261646765732f6c6f676f2d6e6f2d6c6162656c2e737667"&gt;&lt;img src="https://camo.githubusercontent.com/950a0a20abf52af1b9e961d13bf35410771a0f21f11a5004a2997a110b22506b/68747470733a2f2f63646e2e6576696c6d61727469616e732e636f6d2f6261646765732f6c6f676f2d6e6f2d6c6162656c2e737667" alt="" width="22" height="16"&gt;&lt;/a&gt;  Made at &lt;b&gt;&lt;a href="https://evilmartians.com/devtools?utm_source=nanoid&amp;amp;utm_campaign=devtools-button&amp;amp;utm_medium=github" rel="nofollow noopener noreferrer"&gt;Evil Martians&lt;/a&gt;&lt;/b&gt;, product consulting for &lt;b&gt;developer tools&lt;/b&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Table of Contents&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#table-of-contents" rel="noopener noreferrer"&gt;Table of Contents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#comparison-with-uuid" rel="noopener noreferrer"&gt;Comparison with UUID&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#benchmark" rel="noopener noreferrer"&gt;Benchmark&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#security" rel="noopener noreferrer"&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#install" rel="noopener noreferrer"&gt;Install&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ai/nanoid#api" rel="noopener noreferrer"&gt;API&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#blocking" rel="noopener noreferrer"&gt;Blocking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#non-secure" rel="noopener noreferrer"&gt;Non-Secure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#custom-alphabet-or-size" rel="noopener noreferrer"&gt;Custom Alphabet or Size&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#custom-random-bytes-generator" rel="noopener noreferrer"&gt;Custom Random Bytes Generator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ai/nanoid#usage" rel="noopener noreferrer"&gt;Usage&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#react" rel="noopener noreferrer"&gt;React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#react-native" rel="noopener noreferrer"&gt;React Native&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#pouchdb-and-couchdb" rel="noopener noreferrer"&gt;PouchDB and CouchDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#web-workers" rel="noopener noreferrer"&gt;Web Workers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ai/nanoid#cli" rel="noopener noreferrer"&gt;CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ai/nanoid#other-programming-languages" rel="noopener noreferrer"&gt;Other&lt;/a&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ai/nanoid" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>codebytes</category>
      <category>uuid</category>
      <category>nanoid</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Codebytes: provide / inject is a bliss in vue3</title>
      <dc:creator>prakash chokalingam</dc:creator>
      <pubDate>Thu, 20 May 2021 16:29:37 +0000</pubDate>
      <link>https://dev.to/prakash_chokalingam/codebytes-provide-inject-is-a-bliss-in-vue3-2ol9</link>
      <guid>https://dev.to/prakash_chokalingam/codebytes-provide-inject-is-a-bliss-in-vue3-2ol9</guid>
      <description>&lt;p&gt;Before the existence of these wonderful helpers &lt;strong&gt;provide / inject&lt;/strong&gt; from the vue3 &lt;a href="https://v3.vuejs.org/guide/composition-api-provide-inject.html#scenario-background"&gt;composition apis&lt;/a&gt;, if we have to pass props from a top-level component to the child-level components, we have to ensure that the props are passed all the way down or we should rely on state managers like vuex to avoid passing props.&lt;/p&gt;

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

&lt;p&gt;But these new helpers allow us to consume the props in the child components easily from the parent component without passing them redundantly.&lt;/p&gt;

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

&lt;p&gt;Let's look at the below example where the parent component provides the title prop and the child component utilizes the title prop by simply injecting it.&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;// article-component.vue (ancestor)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;provide&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;vue&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="nf"&gt;setup&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Article Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// article-title-component.vue (child)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inject&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;vue&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="nf"&gt;setup&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And what if the child component wants to update the injected prop? Let's provide the update callback as well.&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;// article-component.vue (ancestor)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;provide&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;vue&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="nf"&gt;setup&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Article Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;updateTitle&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="nx"&gt;newTitle&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;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newTitle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// article-title-component.vue (child)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inject&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;vue&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="nf"&gt;setup&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&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;updateTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;updateTitle&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;updateTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Draft: &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="s2"&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;p&gt;See, that's why it's a bliss!&lt;/p&gt;

&lt;p&gt;PS: Used &lt;a href="https://www.figma.com/figjam/"&gt;https://www.figma.com/figjam/&lt;/a&gt; for the quick flow diagrams.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>vue3</category>
      <category>javascript</category>
      <category>codebytes</category>
    </item>
    <item>
      <title>Generating files with 'vue-cli-plugin-pod'</title>
      <dc:creator>prakash chokalingam</dc:creator>
      <pubDate>Sat, 15 May 2021 15:28:18 +0000</pubDate>
      <link>https://dev.to/prakash_chokalingam/generating-files-with-vue-cli-plugin-pod-5639</link>
      <guid>https://dev.to/prakash_chokalingam/generating-files-with-vue-cli-plugin-pod-5639</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b5kIAp4U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://prakashchokalingam.github.io/vue-cli-plugin-pod/logo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b5kIAp4U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://prakashchokalingam.github.io/vue-cli-plugin-pod/logo.png" width="224" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are working on an awesome vue project, give this awesome &lt;a href="https://www.npmjs.com/package/vue-cli-plugin-pod"&gt;vue-cli-pod-plugin&lt;/a&gt; a spin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create your components and its related files in a snap&lt;/li&gt;
&lt;li&gt;Set file path guidelines&lt;/li&gt;
&lt;li&gt;Enforce conventions and rules via default template file content&lt;/li&gt;
&lt;li&gt;Customise and extend the pod configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How?
&lt;/h2&gt;

&lt;p&gt;Add the plugin to your vue project using the below command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vue add pod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;small&gt;To know more about &lt;a href="https://cli.vuejs.org/guide/plugins-and-presets.html#plugins"&gt;vue cli plugins click here&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;

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

&lt;p&gt;Now your project has access to the following pod commands. The tasks can be triggered using yarn or npm.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run &amp;lt;command&amp;gt; &amp;lt;file type&amp;gt; &amp;lt;file name or file path&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The pod CLI plugin allows component, directive and mixin as the default file type. It can also be extended.&lt;/p&gt;
&lt;h3&gt;
  
  
  Generate
&lt;/h3&gt;

&lt;p&gt;The generate command creates files of a given type using the config.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run generate component UI/dropdown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;By default, the vue-pod plugin will use the &lt;a href="https://github.com/prakashchokalingam/vue-cli-plugin-pod/blob/main/src/pod.config.ts"&gt;default configuration&lt;/a&gt; to generate files in the pod structure. It can be overridden by customising the configs using the below config command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nnwfHYnl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media.githubusercontent.com/media/prakashchokalingam/vue-cli-plugin-pod/gh-pages/demo-assets/pod-generate.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nnwfHYnl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://media.githubusercontent.com/media/prakashchokalingam/vue-cli-plugin-pod/gh-pages/demo-assets/pod-generate.gif" alt="pod generate" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Config
&lt;/h3&gt;

&lt;p&gt;The config command creates the &lt;code&gt;pod.config.js&lt;/code&gt; file to the root of your vue project with the default settings. The file can be customised and it will be used by pod cli for further invocations.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Click here to check the &lt;a href="https://github.com/prakashchokalingam/vue-cli-plugin-pod#config"&gt;available configuration options&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;The rename command replaces the generated files with an alternative name.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run rename component UI/Dropdown UI/Selectbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


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

&lt;p&gt;The delete command removes the generated files in the specified path and deletes the directories from the project if it's empty.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run delete component UI/Dropdown UI/Selectbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


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

&lt;p&gt;Vue is incrementally adoptable and it lets you include scalable features like routes, stores(vuex) to your project later. Don't worry! like vue, vue-cli-plugin-pod is also extensible.&lt;/p&gt;

&lt;p&gt;Introduce new file types and their file path in the config at ease.&lt;/p&gt;

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

&lt;p&gt;If you like the plugin, donate a star to the repo 🤩&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/webcored"&gt;
        webcored
      &lt;/a&gt; / &lt;a href="https://github.com/webcored/vue-cli-plugin-pod"&gt;
        vue-cli-plugin-pod
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Extended CLI to manage file templates for vue projects
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt; &lt;p&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/9a799cbd85b51fdc9c2f97198dd2a34c602a33d1a1a7230ff35d2782fa3c28fe/68747470733a2f2f776562636f7265642e6769746875622e696f2f7675652d636c692d706c7567696e2d706f642f6c6f676f2e706e67"&gt;&lt;img src="https://camo.githubusercontent.com/9a799cbd85b51fdc9c2f97198dd2a34c602a33d1a1a7230ff35d2782fa3c28fe/68747470733a2f2f776562636f7265642e6769746875622e696f2f7675652d636c692d706c7567696e2d706f642f6c6f676f2e706e67" height="100px" width="100px"&gt;&lt;/a&gt;
 &lt;/p&gt;
&lt;h1&gt;
vue-cli-plugin-pod&lt;/h1&gt;
&lt;p&gt;Extended cli to manage file templates for vue projects&lt;/p&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/ac2054d3679db5630a367c58848cf210dae7014a9d842d6188ad96f17729316a/68747470733a2f2f666c61742e62616467656e2e6e65742f62616467652f4275696c74253230576974682f547970655363726970742f626c7565"&gt;&lt;img src="https://camo.githubusercontent.com/ac2054d3679db5630a367c58848cf210dae7014a9d842d6188ad96f17729316a/68747470733a2f2f666c61742e62616467656e2e6e65742f62616467652f4275696c74253230576974682f547970655363726970742f626c7565"&gt;&lt;/a&gt;
  &lt;a href="https://www.npmjs.com/package/vue-cli-plugin-pod" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/bf4cde5c6e8f815f242d098f72a8dbaa71cee6e971af3b58131bde28e46b7725/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f7675652d636c692d706c7567696e2d706f643f636f6c6f723d253233323264343232266c6f676f436f6c6f723d253233666666267374796c653d666c61742d737175617265"&gt;
  &lt;/a&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/df94c8a9a0511c3854bb62bfdf64385f0bbe6b16eeff20df09cefd497970f94a/68747470733a2f2f696d672e736869656c64732e696f2f7374617469632f76313f6c6162656c3d6e6f6465266d6573736167653d2533453d25323031322e302e3026636f6c6f723d253233323264343232266c6f676f436f6c6f723d253233666666267374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/df94c8a9a0511c3854bb62bfdf64385f0bbe6b16eeff20df09cefd497970f94a/68747470733a2f2f696d672e736869656c64732e696f2f7374617469632f76313f6c6162656c3d6e6f6465266d6573736167653d2533453d25323031322e302e3026636f6c6f723d253233323264343232266c6f676f436f6c6f723d253233666666267374796c653d666c61742d737175617265"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/4a5b375c2ff15fae4b66eb699a327ade40dab19ea5572fbfe12fa5d6479adb52/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64742f7675652d636c692d706c7567696e2d706f643f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/4a5b375c2ff15fae4b66eb699a327ade40dab19ea5572fbfe12fa5d6479adb52/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64742f7675652d636c692d706c7567696e2d706f643f7374796c653d666c61742d737175617265"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h4&gt;
Refer&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://dev.to/prakash_chokalingam/generating-files-with-vue-cli-plugin-pod-5639" rel="nofollow"&gt;https://dev.to/prakash_chokalingam/generating-files-with-vue-cli-plugin-pod-5639&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Installation&lt;/h2&gt;
&lt;p&gt;Add this &lt;a href="https://cli.vuejs.org/guide/plugins-and-presets.html" rel="nofollow"&gt;vue cli plugin&lt;/a&gt; to your awesome vue project using the below command:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;vue add pod
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;once installed, your project will have access to the following  tasks:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
Generate&lt;/h3&gt;
&lt;p&gt;Creates template files for the specified file type&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;npm run generate &amp;lt;filetype&amp;gt; &amp;lt;file name or path&amp;amp;gt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Example: &lt;code&gt;npm run generate component UI/Button&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
Rename&lt;/h3&gt;
&lt;p&gt;Renames template files for the specified file type&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;npm run rename &amp;lt;filetype&amp;gt; &amp;lt;old file name or path&amp;gt; &amp;lt;new file name or path&amp;amp;gt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Example: &lt;code&gt;npm run rename component icon avatar&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
Delete&lt;/h3&gt;
&lt;p&gt;Deletes template files for the specified file type&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;npm run delete &amp;lt;filetype&amp;gt; &amp;lt;file name or path&amp;amp;gt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Example: &lt;code&gt;npm run delete component UI/Button&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
Config&lt;/h3&gt;
&lt;p&gt;Get a clone of the default pod config file and customize it.&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;npm run config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above command will generate a &lt;code&gt;pod.config.js&lt;/code&gt; file to the root of your project.&lt;/p&gt;
&lt;p&gt;click here to…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/webcored/vue-cli-plugin-pod"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>vue</category>
      <category>vuepod</category>
      <category>vueclipluginpod</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Codebytes: How to mock upload files in the test cases</title>
      <dc:creator>prakash chokalingam</dc:creator>
      <pubDate>Sun, 19 Jul 2020 06:27:42 +0000</pubDate>
      <link>https://dev.to/prakash_chokalingam/codebytes-how-to-mock-upload-files-in-the-test-cases-1g87</link>
      <guid>https://dev.to/prakash_chokalingam/codebytes-how-to-mock-upload-files-in-the-test-cases-1g87</guid>
      <description>&lt;p&gt;Mocking file uploads with file input elements is not straight forward as mocking other HTML elements while writing test cases. Why and how do we do that?&lt;/p&gt;

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

&amp;lt;input type="file" id="file-upload" onchange="doSomething" /&amp;gt;


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

&lt;/div&gt;
&lt;p&gt;The file input elements have &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/FileList" rel="noopener noreferrer"&gt;FileList&lt;/a&gt; object as its value. The FileList is nothing but a collection of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/File" rel="noopener noreferrer"&gt;File&lt;/a&gt; objects. The FileList object is &lt;strong&gt;read-only&lt;/strong&gt; and we &lt;strong&gt;cannot construct custom FileList&lt;/strong&gt; since it has no implementation of its constructor.&lt;/p&gt;

&lt;p&gt;However, there is a way to construct them using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer" rel="noopener noreferrer"&gt;DataTransfer&lt;/a&gt; object.&lt;/p&gt;

&lt;p&gt;DataTransfer object is responsible for holding the file objects in FileList during files drag &amp;amp; drop. We are gonna bypass the DataTransfer event's file addition methods to construct a FileList with our mocked files.&lt;/p&gt;

&lt;p&gt;Let's create one,&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

const dt = () =&amp;gt; new DataTransfer() || new ClipboardEvent('').clipboardData;


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

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;If the browser didn't support constructing a new DataTransfer, let's get the DataTransfer object from the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData" rel="noopener noreferrer"&gt;ClipboardEvent&lt;/a&gt; (mock's file copy-paste) alternatively.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;let's create a blob to construct a file object.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

let fileString = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z/C/HgAGgwJ/lK3Q6wAAAABJRU5ErkJggg==';

(or)

let fileString = 'https://some-image-url.png';

let blob = await fetch(fileString).then(res =&amp;gt; {
  return res.blob();
});


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

&lt;/div&gt;
&lt;p&gt;And now file object,&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

let file = new File([blob], "sample.jpg", { type: 'image/png'})


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

&lt;/div&gt;
&lt;p&gt;will add the file object to the DataTransfer,&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

let dt = dt();
dt.items.add(file);


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

&lt;/div&gt;
&lt;p&gt;and it's time to add the FileList to the file input element&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

let $fileElement = document.getElementById('file-upload');
$fileElement.files = dt.files;


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

&lt;/div&gt;
&lt;p&gt;🎉 Yay! The files have been added to the file element and now let's emit the change event so that your UI can respond to the file upload.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

let changeEvent = new Event('change');
$fileElement.dispatchEvent(changeEvent);


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

&lt;/div&gt;
&lt;p&gt;To ease this, I have created a test helper util to fill files to the file input element.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

await fillInFIle('#file-upload') ✅


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

&lt;/div&gt;
&lt;p&gt;Check the GitHub repo for more details on the util:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/prakashchokalingam" rel="noopener noreferrer"&gt;
        prakashchokalingam
      &lt;/a&gt; / &lt;a href="https://github.com/prakashchokalingam/fill-in-file" rel="noopener noreferrer"&gt;
        fill-in-file
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A test util that helps to fill files in your file input element
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>mockfileupload</category>
      <category>fillinfile</category>
      <category>javascript</category>
      <category>codebytes</category>
    </item>
    <item>
      <title>Codebytes: Caching mongoose models in Redis (MongoDB).</title>
      <dc:creator>prakash chokalingam</dc:creator>
      <pubDate>Wed, 27 May 2020 05:15:59 +0000</pubDate>
      <link>https://dev.to/prakash_chokalingam/codebytes-caching-mongoose-models-in-redis-mongodb-4920</link>
      <guid>https://dev.to/prakash_chokalingam/codebytes-caching-mongoose-models-in-redis-mongodb-4920</guid>
      <description>&lt;p&gt;Ever considered caching your mongoose models in a super caching tool like Redis to avoid frequent MongoDB hit and refrained from doing that because you may lose the mongoose object privileges like calling model._id as model.id or model.toObject() or the superior one &lt;strong&gt;model.populate()&lt;/strong&gt; and others.&lt;/p&gt;

&lt;p&gt;Here comes the saviour,&lt;br&gt;
&lt;a href="https://mongoosejs.com/docs/api.html#model_Model.hydrate"&gt;https://mongoosejs.com/docs/api.html#model_Model.hydrate&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hydrate method in mongoose API converts your raw JSON data into the mongoose model object(s).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Example: Simple model&lt;br&gt;
&lt;/p&gt;

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

let todo = Todo.findById(id);
redis.set(key, todo); // stores as raw json

// read cache

let todoCache = redis.get(key); // returns raw json
let todo = Todo.hydrate(todoCache); // converts in to mongoose model

let createdBy = todo.populate('createdBy'); 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example: Array of models&lt;br&gt;
&lt;/p&gt;

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

let todos = Todo.findAll();
redis.set('todos', todos); // stores as array of son

// read cache

let cachedTodos = redis.get('todos'); // returns array of json
let todos = cachedTodos.map(todo =&amp;gt; Todo.hydrate(todo)); // converts in to mongoose model

let incompleteTodos = todos.filter(todo =&amp;gt; !todo.isDone);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>codebytes</category>
      <category>mongodb</category>
      <category>mongoose</category>
      <category>redis</category>
    </item>
  </channel>
</rss>
