npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ianmaleney/sheets-api-helper

v1.0.0

Published

A helper library for interacting with the Google Sheets API using Node.js.

Readme

Google Sheets API - Complete Authentication Flow

A production-ready authentication system for accessing Google Sheets data using service account credentials.

🎯 What This Provides

Service Account Authentication - Secure, non-interactive API access
Automatic Initialization - Auth is set up automatically on first use
Cached Client - Avoids re-authentication for every request
Error Handling - Clear error messages for debugging
Batch Operations - Fetch multiple ranges efficiently
Integration Tests - Verify API connectivity
Setup Verification - Script to check your configuration

📁 Project Structure

.
├── index.js                    # Main API implementation
├── index.test.js              # Integration tests
├── example.js                 # Usage examples
├── setup-check.js             # Configuration verification script
├── SETUP.md                   # Detailed setup guide
├── AUTH_IMPLEMENTATION.md     # Implementation details
├── README.md                  # This file
├── .env                       # Environment variables (contains TEST_SHEET_ID)
├── .gitignore                 # Git ignore (keeps credentials safe)
├── service_key.json           # Service account key (DO NOT COMMIT)
└── package.json               # Project dependencies

🚀 Quick Start

1. Verify Setup

node setup-check.js

This will check:

  • ✓ service_key.json exists and is valid
  • ✓ TEST_SHEET_ID is set in .env
  • ✓ Dependencies are installed
  • ✓ Credentials are not committed to git

2. Share Your Spreadsheet

  1. Get the service account email from the output above
  2. Open your Google Sheet
  3. Click Share
  4. Paste the service account email
  5. Give it Viewer access (or Editor if needed)

3. Run Example

bun run example.js

4. Run Tests

bun test

📖 API Reference

initializeAuth()

Initialize the Google Sheets API client. Call this once at app startup.

import { initializeAuth } from './index.js';

await initializeAuth();

getSheetData(spreadsheetId, range)

Fetch data from a single spreadsheet range.

const rows = await getSheetData(
  '1ZEs6v0-izIyVNFdBb7B4PXOGXsdsjuTq0tAXJBg_kDU',
  'Sheet1!A1:D10'
);

console.log(rows); // Array of rows

getMultipleRanges(spreadsheetId, ranges)

Fetch multiple ranges efficiently in one API call.

const data = await getMultipleRanges(
  '1ZEs6v0-izIyVNFdBb7B4PXOGXsdsjuTq0tAXJBg_kDU',
  ['Sheet1!A1:D10', 'Sheet2!A1:B5']
);

console.log(data['Sheet1!A1:D10']); // Array of rows
console.log(data['Sheet2!A1:B5']);  // Array of rows

🔧 Configuration

Environment Variables (.env)

TEST_SHEET_ID=your_spreadsheet_id

Get your spreadsheet ID from the URL:

https://docs.google.com/spreadsheets/d/{SPREADSHEET_ID}/edit

Service Key (service_key.json)

Your Google Cloud service account JSON key. Already in .gitignore to prevent accidental commits.

🐛 Troubleshooting

"The caller does not have permission"

Cause: Spreadsheet not shared with service account

Solution:

  1. Get service account email from service_key.jsonclient_email
  2. Share the spreadsheet with this email
  3. Grant at least Viewer access

"Service key not found"

Cause: service_key.json not in project root

Solution:

  1. Download your service account key from Google Cloud Console
  2. Save it as service_key.json in the project root
  3. Never commit it (already in .gitignore)

Authentication Timeout

Cause: Normal for first request

Solution: This is expected. Subsequent requests are faster due to caching.

No data returned

Cause: Empty sheet or invalid range

Solution:

  • Check that the range contains data
  • Verify spreadsheet ID is correct
  • Try a different range like Sheet1!A1:Z100

📚 More Information

🔐 Security

  • service_key.json is in .gitignore
  • ✓ Credentials never logged in production
  • ✓ Uses Google Cloud's official libraries
  • ✓ Service account is recommended over user authentication
  • ✓ Use environment variables for sensitive data

🔄 Workflow Summary

// 1. Import once in your app
import { initializeAuth, getSheetData } from './index.js';

// 2. Initialize once at startup
await initializeAuth();

// 3. Use anytime, anywhere
const rows = await getSheetData('spreadsheet-id', 'Sheet1!A1:D10');

💡 Tips

  • Batch Reads: Use getMultipleRanges() instead of multiple getSheetData() calls
  • Range Format: Use A1 notation like Sheet1!A1:D10 or 'Sheet1'!A1:D10
  • Large Datasets: For very large sheets, consider using pagination
  • Caching: The auth client is cached automatically - no need to reinitialize

🤝 Need Help?

  1. Run node setup-check.js to verify configuration
  2. Check SETUP.md for detailed instructions
  3. See example.js for working code
  4. Review error messages - they indicate the exact issue