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

gdrive-db

v0.1.4

Published

A beginner-friendly database-like storage SDK powered by the end user's own Google Drive. Not a replacement for MongoDB/PostgreSQL/Firebase — built for learning, prototypes, demos, and small frontend projects.

Readme

gdrive-db

npm version npm downloads GitHub stars License: MIT Build Tests TypeScript

A beginner-friendly, database-like storage SDK powered by the end user's own Google Drive.

import { DriveDB, BrowserAuthProvider } from "gdrive-db";

const auth = new BrowserAuthProvider({
  clientId: "YOUR_GOOGLE_OAUTH_CLIENT_ID",
});
const db = await DriveDB.connect({ database: "my-shop", auth });

const users = db.collection<{ name: string; email: string; age: number }>(
  "users",
);

const user = await users.insert({
  name: "Ali",
  email: "[email protected]",
  age: 19,
});
const allUsers = await users.find();
const ali = await users.findOne({ email: "[email protected]" });
await users.update(user.id, { age: 20 });
await users.delete(user.id);

Simple Guide (Roman Urdu / Hindi)

Agar aap beginner hain aur simple lafzon mein samajhna chahte hain ke ye package frontend mein kaise connect hota hai, ye guide aapke liye hai.

Step 1: Google Cloud setup (ek baar karna hai)

  1. Google Cloud Console par jaake ek project banayein.
  2. Google Drive API enable karein (APIs & Services -> Library -> "Google Drive API" -> Enable).
  3. OAuth consent screen configure karein — personal project ke liye "External" + apne aap ko test user mein add karein.
  4. Credentials -> Create Credentials -> OAuth client ID -> Web application choose karein, aur apne app ka origin (jaise http://localhost:5173 ya http://localhost:3000) "Authorized JavaScript origins" mein add karein.
  5. Yahan se aapko ek Client ID milega (kuch aisa: xxxx.apps.googleusercontent.com) — ye public hai, browser code mein rakh sakte hain.

Step 2: Package install karein

npm install gdrive-db

Step 3: Frontend code mein connect karein

import { DriveDB, BrowserAuthProvider } from "gdrive-db";

const auth = new BrowserAuthProvider({
  clientId: "YOUR_GOOGLE_OAUTH_CLIENT_ID",
});

const db = await DriveDB.connect({ database: "my-shop", auth });

const users = db.collection<{ name: string; email: string; age: number }>(
  "users",
);

// Insert
const user = await users.insert({
  name: "Ali",
  email: "[email protected]",
  age: 19,
});

// Read
const allUsers = await users.find();

// Update
await users.update(user.id, { age: 20 });

// Delete
await users.delete(user.id);

Ye kaam kaise karta hai

  • Jaise hi pehla Drive operation call hota hai, Google ka sign-in popup khulega — user apne Google account se login karega.
  • Data user ke apne Google Drive mein DataLens/my-shop/ folder ke andar JSON files (users.json waghera) ki shakal mein save hota hai.
  • Token sirf memory mein rehta hai (page reload par dobara login karna padega), koi server backend ki zaroorat nahi.
  • Sirf drive.file scope use hota hai — matlab app sirf apni banai hui files access karta hai, poori Drive nahi.

Important baatein

  • Ye ek per-user storage hai — sab users ka data ek jagah share nahi hota, har user ka apna Drive.
  • Ye production-grade database nahi hai (koi transactions/concurrency control nahi) — beginner projects, prototypes, demos ke liye best hai.
  • Agar server-side (Node) use karna hai to gdrive-db/node se NodeAuthProvider use karein — lekin uske liye client secret aur refresh token chahiye hote hain jo kabhi bhi frontend code mein nahi jaane chahiye.

What it is

gdrive-db gives your app a small collection/document API — insert, find, findOne, update, delete — while the actual data lives as JSON files inside a DataLens folder in the signed-in user's own Google Drive. There is no shared backend, no database you have to host, and no bill: each user's data lives in their own Drive, under their own quota.

Why it exists

Beginners building a first app, a class project, or a weekend prototype often need "somewhere to put the data" without standing up Postgres, Mongo, or Firebase and wiring up hosting, billing, and security rules. This package trades scale and guarantees for near-zero setup: sign in with Google, and you have a working per-user data store.

Who should use it

  • Beginner developers and students learning to build apps with persistent data
  • Small frontend projects, demos, and hackathon prototypes
  • Hobby projects where "my own Google Drive" is an acceptable place to keep data

Who should NOT use it

  • Anyone needing a shared/multi-user backend. Every collection lives in one Google account's Drive; there is no built-in way for multiple users to read/write the same dataset.
  • Anyone needing production guarantees. No transactions, no concurrency control, no SLA, no indexing, no horizontal scale. See Limitations.
  • Anyone who needs this to just work without the user signing in to Google. There is no "headless"/anonymous mode for end users — see Authentication.

This is not a free MongoDB, Postgres, or Firebase replacement. Think of it as: use your own Google Drive as a simple database backend for small frontend projects and prototypes.

Architecture

Developer Application
        |
        v
gdrive-db
        |
        v
Google OAuth (Identity Services, browser)  /  refresh-token OAuth (Node, server)
        |
        v
Google Drive REST API
        |
        v
User's own Google Drive
        |
        v
DataLens/<database>/
        ├── users.json
        ├── products.json
        └── orders.json

Internally the package is layered so each piece can be tested and reasoned about independently:

  • auth — obtains a live Drive access token (TokenProvider interface). Two interchangeable implementations: BrowserAuthProvider (browser) and NodeAuthProvider (server, separate entry).
  • driveDriveClient, a thin fetch-based wrapper over the Drive REST v3 API (find/create folders and files, read/update/delete file content). Internal only.
  • storageCollectionStore, a JSON-file-per-collection abstraction on top of DriveClient.
  • databaseDriveDB (connect, createCollection, listCollections, collection()) and CollectionImpl (the actual CRUD methods you call).

Installation

npm install gdrive-db

For server-side/Node usage of NodeAuthProvider, also install the optional peer dependency:

npm install googleapis

Authentication

This is the part beginners get wrong most often when reaching for Drive as a backend, so it's worth being explicit: there is no way to talk to a user's private Google Drive without that user signing in with Google. This package never asks for more than that.

Browser (the primary, recommended path)

BrowserAuthProvider uses Google Identity Services (GIS) — the current Google-recommended way to get an OAuth access token directly in a browser. It needs only a public OAuth Client ID, never a client secret:

import { BrowserAuthProvider, DriveDB } from "gdrive-db";

const auth = new BrowserAuthProvider({
  clientId: "xxxx.apps.googleusercontent.com",
});
const db = await DriveDB.connect({ database: "my-shop", auth });
  • The first Drive operation triggers Google's sign-in/consent popup.
  • Access tokens are cached in memory only for the lifetime of the page — never written to localStorage, sessionStorage, IndexedDB, or cookies. Reloading the page requires signing in again. Call auth.signOut() to discard the cached token explicitly.
  • No server component is required for this flow.

Server / Node (optional, advanced)

For a backend service that needs to act on Drive without a user present in a browser, NodeAuthProvider (from the separate gdrive-db/node entry) uses a long-lived Google OAuth refresh token:

import { NodeAuthProvider } from "gdrive-db/node";
import { DriveDB } from "gdrive-db";

const auth = new NodeAuthProvider({
  clientId: process.env.GOOGLE_OAUTH_CLIENT_ID!,
  clientSecret: process.env.GOOGLE_OAUTH_CLIENT_SECRET!,
  refreshToken: process.env.GOOGLE_OAUTH_REFRESH_TOKEN!,
});
const db = await DriveDB.connect({ database: "my-shop", auth });

This entry point is kept completely separate from the main package export (a different file, marked external in the build) so bundlers building browser code never see a reference to googleapis, and a client secret can never accidentally end up in a browser bundle. You obtain the refresh token yourself, once, through your own server-side OAuth consent flow — this package does not provide that flow, since it's inherently specific to your backend.

Never put clientSecret or refreshToken in browser code, in a NEXT_PUBLIC_*/VITE_* variable, or anywhere a client can read it.

Google Cloud setup

  1. Go to the Google Cloud Console and create (or select) a project.
  2. Enable the Google Drive API for that project (APIs & Services -> Library -> "Google Drive API" -> Enable).
  3. Configure the OAuth consent screen (APIs & Services -> OAuth consent screen). For personal projects, "External" + test users is usually the right choice while developing.
  4. Create credentials (APIs & Services -> Credentials -> Create Credentials -> OAuth client ID):
    • For browser usage: Web application, with your app's origin(s) under "Authorized JavaScript origins". This gives you the public Client ID used by BrowserAuthProvider.
    • For server usage only: create a client ID/secret and obtain a refresh token yourself via a one-time OAuth consent flow you run on your server.
  5. Copy .env.example to .env and fill in your own values. Never commit .env.

Required scope

The package requests only:

https://www.googleapis.com/auth/drive.file

This is Google's least-privilege Drive scope: it grants access only to files/folders the app itself creates, not the user's entire Drive. gdrive-db never asks for broader access than this.

Environment configuration

See .env.example. GOOGLE_OAUTH_CLIENT_ID is public and safe to ship in browser code. GOOGLE_OAUTH_CLIENT_SECRET and GOOGLE_OAUTH_REFRESH_TOKEN are server-only secrets — only needed for NodeAuthProvider, and must never reach browser code or version control.

Usage

import { DriveDB, BrowserAuthProvider } from "gdrive-db";

interface User {
  name: string;
  email: string;
  age: number;
}

const auth = new BrowserAuthProvider({ clientId: "YOUR_CLIENT_ID" });
const db = await DriveDB.connect({ database: "my-shop", auth });

const users = db.collection<User>("users");

CRUD examples

// Create
const user = await users.insert({
  name: "Ali",
  email: "[email protected]",
  age: 19,
});
const many = await users.insertMany([
  { name: "Ahmed", email: "[email protected]", age: 22 },
  { name: "Sara", email: "[email protected]", age: 25 },
]);

// Read
const all = await users.find();
const nineteen = await users.find({ age: 19 });
const ali = await users.findOne({ email: "[email protected]" });
const byId = await users.findById(user.id);
const total = await users.count();
const isThere = await users.exists(user.id);

// Update (partial — other fields are left untouched)
await users.update(user.id, { age: 20 });

// Delete
await users.delete(user.id);

// Collections
await db.createCollection("orders");
const names = await db.listCollections(); // ["users", "orders"]
await users.drop(); // deletes users.json entirely

Collection API

| Method | Description | | --------------------- | --------------------------------------------------------------- | | insert(doc) | Insert one document, returns it with a generated id. | | insertMany(docs) | Insert multiple documents at once. | | find(filter?) | Return matching documents (equality filter, or all if omitted). | | findOne(filter?) | Return the first match, or null. | | findById(id) | Return the document with this id, or null. | | update(id, updates) | Partially update a document by id. Throws if not found. | | delete(id) | Remove a document by id. Returns true/false. | | count(filter?) | Count matching documents. | | all() | Return every document in the collection. | | exists(id) | Whether a document with this id exists. | | drop() | Delete the collection's JSON file from Drive entirely. |

Documents may contain strings, numbers, booleans, null, arrays, and nested objects — anything JSON.stringify can represent. A document must not include its own id field; ids are always generated by the package.

Limitations

  • MVP filters are equality-only. find({ age: 19 }) matches documents where age === 19. There is no $gt/$lt/$in/etc. yet (see Future roadmap).
  • No pagination. find()/all() load the entire collection file into memory every time.
  • No indexing. Every read scans the full collection.
  • Nested data works, but stays JSON-only. No binary data, dates are plain strings/numbers you serialize yourself, no Map/Set/custom classes.

Security

  • Data lives inside the signed-in user's own Google Drive, under DataLens/<database>/. It is never made public and never shared via "anyone with the link" — every request is authenticated per-user through OAuth.
  • The package requests the least-privilege drive.file scope: only files/folders it creates itself, not the user's whole Drive.
  • This package never sees or handles the user's Google password — only an OAuth access token, obtained through Google's own sign-in UI.
  • Browser access tokens are kept in memory only; nothing is written to localStorage or similar.
  • A Node client secret / refresh token, if you use NodeAuthProvider, is your responsibility to store securely (environment variables, a secrets manager) — this package never logs or persists them.
  • This package cannot make claims about the security of your Google account itself. You remain responsible for your own Google account security (strong password, 2FA, reviewing connected apps). Nothing here is "100% secure" or "completely private" — it inherits whatever security posture your Google account and network have.

Concurrency

Google Drive is not a transactional database. Every write reads the whole collection file, applies the change, and writes the whole file back. If two writers touch the same collection at nearly the same time, the second write can silently overwrite the first (a read-modify-write race) — there is no locking, no conflict detection, and no ACID guarantee in this MVP. This package is intended for small, low-concurrency projects: one user, or a small number of collaborators who aren't writing to the same collection at the same instant. Do not use it for anything where lost writes are unacceptable.

Storage & quota considerations

Even though Google Drive accounts often have generous storage quotas, this package is still constrained by:

  • Browser/Node memory (a whole collection is loaded into memory per operation)
  • Google Drive API rate limits and quotas
  • Network speed (every read/write is a round trip to Drive)
  • JSON file size (very large collections get slow to read/write, not just to store)

For the MVP, each collection is one JSON file. Sharding/chunking large collections is a possible future improvement, not implemented now.

Development

npm install
npm run dev      # tsup --watch
npm run build     # ESM + CJS + .d.ts output in dist/
npm run typecheck

Testing

npm test          # vitest run
npm run test:watch

Tests never make real Google API calls. DriveClient is tested against an injected fetch mock; higher layers (CollectionStore, CollectionImpl, DriveDB) are tested against a shared in-memory FakeDriveClient test double, so the whole connect → CRUD flow is exercised without any network access.

Build

npm run build

Produces dist/index.{js,mjs,d.ts} (main, browser-safe entry) and dist/node.{js,mjs,d.ts} (server-only entry, gdrive-db/node).

Publishing

Not published yet. Before publishing, verify the package contents:

npm pack --dry-run

Confirm the tarball contains only dist/, README.md, and LICENSE — no test files, no .env, no remaining-tasks.md, no source .ts files.

Future roadmap

Not implemented yet, listed here as ideas for later versions:

  • Pagination, sorting, and advanced filter operators ($gt, $lt, $in, etc.)
  • Batch writes and write-conflict detection
  • File chunking/sharding for large collections
  • Compression and client-side encryption
  • Realtime sync and offline mode
  • Alternate backends (Google Sheets, local SQLite, Supabase, Firebase)
  • Migration tools, admin UI

Author

Built by Syed Muhammad Ali.

License

MIT — see LICENSE.