<?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: Sameer Charles</title>
    <description>The latest articles on DEV Community by Sameer Charles (@sameercharles).</description>
    <link>https://dev.to/sameercharles</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%2F244143%2F35594d72-e75b-4da3-8555-e9fff00d2af8.png</url>
      <title>DEV Community: Sameer Charles</title>
      <link>https://dev.to/sameercharles</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sameercharles"/>
    <language>en</language>
    <item>
      <title>A small experiment with DoH in browser</title>
      <dc:creator>Sameer Charles</dc:creator>
      <pubDate>Sun, 05 Jun 2022 05:22:42 +0000</pubDate>
      <link>https://dev.to/sameercharles/a-small-experiment-with-doh-in-browser-11c4</link>
      <guid>https://dev.to/sameercharles/a-small-experiment-with-doh-in-browser-11c4</guid>
      <description>&lt;p&gt;I wanted to explore some new uses cases for DoH (DNS over HTTPS). The criteria was simple, anything thats useful for at least one person (thats usually just me) so I was set for the success.&lt;/p&gt;

&lt;p&gt;I work with startups, from naming product, implementation to marketing. So I decided to build a small tool to find available domain names directly from the browser. That is, without using registrar's slow and sluggish websites.&lt;/p&gt;

&lt;p&gt;Using a DNS resolver for domain lookup is not a fool proof method since it will result in false positives if the registrar has misconfigured the domain or if the registry have the domain as not reservable. Either way I decided to give it a go.&lt;/p&gt;

&lt;p&gt;I used Node.js, &lt;a href="https://wordnet.princeton.edu/"&gt;WordNet data source&lt;/a&gt; for the dictionary and &lt;a href="https://developers.cloudflare.com/1.1.1.1/"&gt;Cloudflare open DNS&lt;/a&gt; which is capable of DoH.&lt;/p&gt;

&lt;p&gt;I will eventually open source the entire project (once cleaned up) but here is a quick snippet so you know how easy it is to do a lookup from your browser.&lt;/p&gt;

&lt;p&gt;// Add doh.min.js&lt;br&gt;
&lt;code&gt;https://cdn.jsdelivr.net/npm/dohjs@latest/dist/doh.min.js&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
// Using cloudflare open dns resolver&lt;br&gt;
&lt;code&gt;const DNS = new doh.DohResolver('https://1.1.1.1/dns-query')&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;code&gt;DNS.query('KickSmart.app', 'A')&lt;br&gt;
   .then(response =&amp;gt; {&lt;br&gt;
     const available = response.rcode == 'NXDOMAIN' ? true : false&lt;br&gt;
     console.log('KickSmart.app is avaiable: '+available)&lt;br&gt;
    })&lt;br&gt;
    .catch(err =&amp;gt; {&lt;br&gt;
        console.error(err)&lt;br&gt;
    })&lt;br&gt;
    .finally(() =&amp;gt; {&lt;br&gt;
        console.log('Finished query!')&lt;br&gt;
    })&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Thats it!&lt;/p&gt;

&lt;p&gt;Here I am using Cloudflare open DNS but you can use any available DNS resolver capable of DoH like &lt;a href="https://developers.google.com/speed/public-dns/docs/doh"&gt;google open dns&lt;/a&gt; (used by Chrome) or your own DNS resolver.&lt;/p&gt;

&lt;p&gt;As mentioned above, you will get some false positives time to time. But having the ability to privately and quickly search for domains made it worth.&lt;/p&gt;

&lt;p&gt;The name of the project is &lt;a href="https://idearamen.com/"&gt;IDEA Ramen&lt;/a&gt;, it's a simple yet powerful domain name generator.&lt;/p&gt;

&lt;p&gt;All feedback and questions are welcome!&lt;/p&gt;




</description>
    </item>
    <item>
      <title>Firestore simple string search</title>
      <dc:creator>Sameer Charles</dc:creator>
      <pubDate>Sun, 02 May 2021 22:11:50 +0000</pubDate>
      <link>https://dev.to/sameercharles/firestore-simple-string-search-2dab</link>
      <guid>https://dev.to/sameercharles/firestore-simple-string-search-2dab</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post uses javascript, however you can apply this concept to any firebase client.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can query firestore (a firebase db) quite easily. But when it comes to string search; they dropped the ball and send you to third party search solutions. There is nothing wrong with that if your project needs a full text search; but what if you just want a simple string starts with search (like*)? hopefully firestore will do something about this.&lt;/p&gt;

&lt;p&gt;For now, let me share what I have done for IPster. &lt;a href="https://ipster.io"&gt;IPster app&lt;/a&gt; needed a simple search by first name. And for now we didn't wanted to invest in or use systems like Algolia (nothing against Algolia, I love the product and we probably be using it in the future).&lt;/p&gt;

&lt;p&gt;So how do you search firestore for something like 'get me all documents where name starts with sam'&lt;/p&gt;

&lt;h2&gt;
  
  
  Using firebase javascript client
&lt;/h2&gt;

&lt;p&gt;This should work for most languages.&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;searchTerm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;strlength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;strFrontCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;strlength&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;strEndCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strlength&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// This is an important bit..&lt;/span&gt;
&lt;span class="nx"&gt;endCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;strFrontCode&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromCharCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strEndCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charCodeAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Query using the start and end codes and you will be able to get the same results as you would in traditional databases LIKE 'a%'&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;collectionName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fieldName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fieldName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;endCode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. You should be able to do simple 'starts with' search now. It's a good practice to limit the result set since Firebase will charge you for all documents returned. And if you are using firebase in an open project, you can also setup rules to limit the query results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Angularfire
&lt;/h2&gt;

&lt;p&gt;For IPster we are using Angular fire which makes dealing with complex queries a little easier. Let me give you an example of how we implemented a simple starts with query together with Observable and switchMap&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;Observable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;combineLatest&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;rxjs&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;switchMap&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;rxjs/operators&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;startCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;endCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Once only, in your constructor or init&lt;/span&gt;
&lt;span class="nx"&gt;searchResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;combineLatest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;endCode&lt;/span&gt;
 &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="nx"&gt;switchMap&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;startCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;endCode&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;fireStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;collectionName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fieldName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startCode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fieldName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;endCode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;valueChanges&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="c1"&gt;// Prepare endCode and searchTerm as described in the previous section&lt;/span&gt;
&lt;span class="c1"&gt;// Now you can change the query and get the results (search as you type etc..)&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;endCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;endCode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There you have it.&lt;/p&gt;

</description>
      <category>search</category>
      <category>firebase</category>
      <category>firestore</category>
      <category>angular</category>
    </item>
  </channel>
</rss>
