<?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: Mayank Singh Kushwah</title>
    <description>The latest articles on DEV Community by Mayank Singh Kushwah (@msrajawat298).</description>
    <link>https://dev.to/msrajawat298</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F822491%2F750d6c9a-819d-4178-93ba-99511a05cded.jpeg</url>
      <title>DEV Community: Mayank Singh Kushwah</title>
      <link>https://dev.to/msrajawat298</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/msrajawat298"/>
    <language>en</language>
    <item>
      <title>An open-source Google Business Profile SDK with automatic OAuth refresh, pagination and retries.</title>
      <dc:creator>Mayank Singh Kushwah</dc:creator>
      <pubDate>Sun, 28 Jun 2026 17:17:08 +0000</pubDate>
      <link>https://dev.to/msrajawat298/an-open-source-google-business-profile-sdk-with-automatic-oauth-refresh-pagination-and-retries-1e8g</link>
      <guid>https://dev.to/msrajawat298/an-open-source-google-business-profile-sdk-with-automatic-oauth-refresh-pagination-and-retries-1e8g</guid>
      <description>&lt;p&gt;Over the last few months I was working on a project that manages hundreds of Google Business Profile locations.&lt;/p&gt;

&lt;p&gt;I expected the integration to be straightforward, but the API turned out to be much harder than I anticipated.&lt;/p&gt;

&lt;p&gt;The biggest pain points were:&lt;br&gt;
• OAuth access tokens expiring every hour&lt;br&gt;
• Refresh token race conditions&lt;br&gt;
• Manual pagination using nextPageToken&lt;br&gt;
• Handling 429 rate limits and random 503 responses&lt;br&gt;
• Writing the same boilerplate for every project&lt;/p&gt;

&lt;p&gt;After solving these problems multiple times, I decided to extract everything into an open-source SDK.&lt;/p&gt;

&lt;p&gt;Some features:&lt;br&gt;
✅ Automatic OAuth token refresh&lt;br&gt;
✅ Thread-safe token management&lt;br&gt;
✅ Auto-pagination (fetch all pages automatically)&lt;br&gt;
✅ Built-in retry with exponential backoff&lt;br&gt;
✅ Fully typed TypeScript API&lt;br&gt;
✅ Zero runtime dependencies&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="nx"&gt;Example&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;GBPClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ConsoleLogger&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;@vitabletech/gbp-sdk&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GBPClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_GOOGLE_CLIENT_ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_GOOGLE_CLIENT_SECRET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;refreshToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_REFRESH_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tokenStorage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;span class="c1"&gt;// stores tokens in gbp-tokens.json&lt;/span&gt;
  &lt;span class="na"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ConsoleLogger&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; 
&lt;span class="c1"&gt;// optional pluggable logger&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;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// Automatically handles token generation and pagination!&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listAll&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&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;accountName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;accounts&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;name&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;locations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accountName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Found &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;locations&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="s2"&gt; locations for &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;accountName&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;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project is completely open source.&lt;/p&gt;

&lt;p&gt;I'd really appreciate feedback from anyone who has worked with the Google Business Profile API.&lt;/p&gt;

&lt;p&gt;What features would you want to see next?&lt;/p&gt;

&lt;p&gt;GitHub:&amp;nbsp;&lt;a href="https://github.com/vitabletech/gbp-sdk" rel="noopener noreferrer"&gt;https://github.com/vitabletech/gbp-sdk&lt;/a&gt;&lt;br&gt;
npm:&amp;nbsp;&lt;a href="https://www.npmjs.com/package/@vitabletech/gbp-sdk" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@vitabletech/gbp-sdk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>google</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Implementing Best Practices for Developing an NPM Package with Automated Testing and Deployment</title>
      <dc:creator>Mayank Singh Kushwah</dc:creator>
      <pubDate>Sun, 26 Mar 2023 06:43:09 +0000</pubDate>
      <link>https://dev.to/msrajawat298/implementing-best-practices-for-developing-an-npm-package-with-automated-testing-and-deployment-1pff</link>
      <guid>https://dev.to/msrajawat298/implementing-best-practices-for-developing-an-npm-package-with-automated-testing-and-deployment-1pff</guid>
      <description>&lt;p&gt;In this repository, I have implemented an npm package that contains some useful common functions. These functions should be tested using unit test cases, and the syntax and format should be checked by ESLint during development.&lt;/p&gt;

&lt;p&gt;Before committing the code, I have set up a pre-commit hook that checks the unit test cases and code coverage. If all the unit test cases pass, the code is ready for the commit. Additionally, I have set up a commit message format using the conventional commit standard, and the files are automatically formatted using Prettier before committing.&lt;/p&gt;

&lt;p&gt;To push the code, you need to create a branch and generate a pull request. Once the pull request is created, SonarQube checks the code for bugs, code smells, vulnerabilities, and shows the code coverage. If there are any bugs, the pull request will not be accepted by the admin.&lt;/p&gt;

&lt;p&gt;Once the pull request is accepted, it is merged into the main branch. After the merge, a workflow is triggered that generates the documentation of our functions and deploys it to the GitHub Pages.&lt;/p&gt;

&lt;p&gt;If you create a tag and release the branch, an npm package is automatically created and published on the official npm package site. To download or install the package, you can run the command "npm install".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/vitabletec/general-js-toolkit"&gt;GitHub Repository URL&lt;/a&gt;&lt;br&gt;
&lt;a href="https://vitabletec.github.io/general-js-toolkit/"&gt;Documentation GitHub Pages URL&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/general-js-toolkit"&gt;NPM Package URL&lt;/a&gt;&lt;br&gt;
&lt;a href="https://sonarcloud.io/organizations/vitabletec/projects"&gt;SonarQube Report&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>githubpage</category>
      <category>sonarqube</category>
      <category>msrajawat298</category>
    </item>
  </channel>
</rss>
