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

fires2rest

v0.3.0

Published

Lightweight Firestore REST API client with full transaction support for serverless environments

Downloads

691

Readme

Fires2REST

Fires2REST (Firestore REST with Transactions) is a TypeScript library that provides a simple and efficient way to perform transactions and other operations on Firestore documents using the REST API.

It's a drop-in replacement for the official Firebase Admin SDK (the Firestore part), see the comparison.

Why "Fires2REST"

Firestore REST with Transactions → Firestore REST → FirestoREST → Fires2REST

Features

  • 🔥 Full Firestore REST API support - CRUD operations via REST
  • Transaction support - Atomic reads and writes with automatic retry
  • 🔍 Query support - Filter, order, limit, and paginate collections
  • 🌐 Serverless ready - Works in Cloudflare Workers, Deno, Bun, and any JS runtime
  • 🧪 Emulator support - Local development with Firebase Emulator
  • 📦 Lightweight - The only dependency is jose for JWT auth
  • 🔄 FieldValue support - serverTimestamp, increment, delete, arrayUnion, arrayRemove

Installation

pnpm install fires2rest

Quick Start

import { Firestore, FieldValue } from "fires2rest";

// Initialize with service account credentials
const db = Firestore.useServiceAccount("your-project-id", {
    clientEmail: "[email protected]",
    privateKey: "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
});

// Get a document
const userRef = db.doc("users/alice");
const snap = await userRef.get();

if (snap.exists) {
    console.log(snap.data()); // { name: "Alice", age: 30 }
}

// Set a document
await userRef.set({
    name: "Alice",
    age: 30,
    createdAt: FieldValue.serverTimestamp(),
});

// Update a document
await userRef.update({
    age: 31,
    visits: FieldValue.increment(1),
});

// Delete a document
await userRef.delete();

Transactions

Transactions provide atomic read-modify-write operations:

// Transfer balance between accounts
const result = await db.runTransaction(async (txn) => {
    const fromRef = db.doc("accounts/alice");
    const toRef = db.doc("accounts/bob");

    const fromSnap = await txn.get(fromRef);
    const toSnap = await txn.get(toRef);

    const fromBalance = fromSnap.data()?.balance ?? 0;
    const toBalance = toSnap.data()?.balance ?? 0;

    if (fromBalance < 100) {
        throw new Error("Insufficient balance");
    }

    txn.update(fromRef, { balance: fromBalance - 100 });
    txn.update(toRef, { balance: toBalance + 100 });

    return { transferred: 100 };
});

API Reference

See API Reference for detailed documentation.

Firestore

Main client class.

Static Factory Methods:

// Using service account (for server-side usage)
const db = Firestore.useServiceAccount(projectId, {
    clientEmail: "[email protected]",
    privateKey: "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
}, databaseId?);

// Using Firebase Emulator (for local development)
const db = Firestore.useEmulator({
    emulatorHost: "127.0.0.1:8080",  // optional, defaults to "127.0.0.1:8080"
    projectId: "demo-project",       // optional, defaults to "demo-no-project"
    databaseId: "(default)",         // optional, defaults to "(default)"
    admin: true,                     // optional, defaults to true (bypasses security rules)
});

Methods:

  • collection(path) - Get a CollectionReference
  • doc(path) - Get a DocumentReference
  • runTransaction(updateFn, options?) - Run a transaction

DocumentReference<T>

Reference to a document.

Properties:

  • id - Document ID
  • path - Full document path
  • parent - Parent CollectionReference

Methods:

  • get() - Get document snapshot
  • set(data, options?) - Set document data (options: { merge: boolean })
  • update(data) - Update document fields
  • delete() - Delete document
  • collection(path) - Get a subcollection

CollectionReference<T>

Reference to a collection.

Properties:

  • id - Collection ID
  • path - Full collection path

Methods:

  • doc(id?) - Get a DocumentReference (auto-generates ID if not provided)
  • add(data) - Add document with auto-generated ID
  • where(field, op, value) - Filter by field value
  • orderBy(field, direction?) - Order results
  • limit(n) / limitToLast(n) - Limit results
  • offset(n) - Skip results
  • startAt(...values) / startAfter(...values) - Cursor pagination
  • endAt(...values) / endBefore(...values) - Cursor pagination
  • select(...fields) - Field projection
  • get() - Execute query and return QuerySnapshot
  • count() - Count matching documents

Queries

Build queries using chainable methods:

// Filter, order, and limit
const snapshot = await db
    .collection("users")
    .where("age", ">=", 18)
    .where("active", "==", true)
    .orderBy("createdAt", "desc")
    .limit(10)
    .get();

// Iterate results
snapshot.forEach((doc) => {
    console.log(doc.id, doc.data());
});

// Count documents
const countSnap = await db
    .collection("users")
    .where("active", "==", true)
    .count();
console.log("Active users:", countSnap.data().count);

// Cursor-based pagination
const page2 = await db
    .collection("users")
    .orderBy("name")
    .startAfter("Alice")
    .limit(10)
    .get();

Supported filter operators:

  • ==, != - Equality
  • <, <=, >, >= - Comparison
  • array-contains, array-contains-any - Array queries
  • in, not-in - Inclusion queries

FieldValue

Special field values for atomic operations.

FieldValue.serverTimestamp(); // Server-generated timestamp
FieldValue.increment(n); // Increment numeric field by n
FieldValue.delete(); // Delete this field
FieldValue.arrayUnion(...elements); // Add unique elements to array
FieldValue.arrayRemove(...elements); // Remove elements from array

GeoPoint

Represents a geographic coordinate.

const location = new GeoPoint(37.7749, -122.4194);

Timestamp

Represents a timestamp with nanosecond precision.

const now = Timestamp.now();
const fromDate = Timestamp.fromDate(new Date());
const fromMillis = Timestamp.fromMillis(Date.now());

Type Safety

Use generics for type-safe document data:

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

const userRef = db.doc("users/alice") as DocumentReference<User>;
const snap = await userRef.get();

const user = snap.data(); // User | undefined
console.log(user?.name); // TypeScript knows this is string

Emulator Support

Use the Firebase Emulator for local development and testing:

import { Firestore } from "fires2rest";

// Connect to local emulator with all defaults
const db = Firestore.useEmulator();

// Or customize the connection
const db = Firestore.useEmulator({
    emulatorHost: "127.0.0.1:8095",
    projectId: "demo-no-project",
    admin: true,  // bypass security rules
});

Start the Firebase Emulator:

pnpm firebase emulators:start

Environment Variables

Set up your service account credentials:

FIREBASE_PROJECT_ID=your-project-id
FIREBASE_CLIENT_EMAIL=your-service-account@project.iam.gserviceaccount.com
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"

# For emulator usage
FIRESTORE_EMULATOR_HOST=127.0.0.1:8095

License

MIT