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

@grace-studio/firebase-server

v0.0.1-beta.0

Published

Server-side Firebase utilities for Firebase Functions

Readme

@grace-studio/firebase-server

Server-side Firebase utilities for Firebase Functions.

Installation

npm install @grace-studio/firebase-server

Modules

This package provides server-side utilities for Firebase Functions.

For client-side React utilities, see @grace-studio/firebase-react (coming soon).

OTP Module

The OTP module provides one-time password functionality with email delivery for Firebase functions.

Basic Usage

import { onCall } from "firebase-functions/https";
import { onSchedule } from "firebase-functions/scheduler";
import { getApp } from "firebase-admin/app";
import {
  otp,
  OTPConfigCommon,
  OTPConfigInitialize,
} from "@grace-studio/firebase-server";

// Get your Firebase Admin app instance
const app = getApp();

// Shared configuration used by both endpoints
const sharedConfig: OTPConfigCommon = {
  app, // Firebase Admin app instance
  firestoreCollectionPath: "otp_codes", // Firestore collection to store OTP data
};

// Optional: Configure logging level for debugging
// Options: "verbose", "regular"
otp.configureLogger("verbose");

/**
 * Endpoint 1: Initialize OTP Sign-in
 *
 * This endpoint generates a new OTP code and sends it via email.
 * Call this when a user wants to sign in with their email.
 *
 * Expected request data: { email: string }
 * Returns: { newUser: boolean, otpTTL: number, expiresAt: Timestamp }
 */
export const initializeOTPSignIn = onCall({}, async (req) => {
  const { email } = req.data;

  const config: OTPConfigInitialize = {
    ...sharedConfig,

    // Security settings
    saltRounds: 6, // bcrypt salt rounds for hashing OTP
    maxSignInAttempts: 3, // Max failed validation attempts before blocking

    // OTP settings
    otpLength: 8, // Length of the generated OTP code (default: 8)
    otpTTL: 600, // Time-to-live in seconds (10 minutes)

    // Optional: Custom OTP generator function
    // customOtpGenerator: (length) => nanoid(),

    // Email configuration
    nodeMailerConfig: {
      smtp: {
        host: "smtp.ethereal.email", // Your SMTP server
        port: 587, // SMTP port (587 for TLS, 465 for SSL)
        auth: {
          user: "[email protected]", // SMTP username
          pass: "your-password", // SMTP password
        },
      },
      email: {
        from: '"Your App Name" <[email protected]>', // Sender info

        // Email templates with template variables
        // Available variables: {otp} and {email}
        subjectTemplate: "One time password for Your App - {otp}",

        // HTML email body (supports HTML tags)
        htmlTemplate: `
          <h2>Welcome to Your App!</h2>
          <p>Hi {email}!</p>
          <p>Your one-time password is: <strong style="font-size: 24px; color: #007bff;">{otp}</strong></p>
          <p>This code will expire in 10 minutes.</p>
          <p>If you didn't request this, please ignore this email.</p>
        `,

        // Plain text email body (fallback for email clients that don't support HTML)
        textTemplate: `
          Welcome to Your App!
          Hi {email}!
          Your one-time password is: {otp}
          This code will expire in 10 minutes.
          If you didn't request this, please ignore this email.
        `,
      },
    },
  };

  // Generate OTP and send email
  return otp.initialize(config)(email);
});

/**
 * Endpoint 2: Validate OTP
 *
 * This endpoint validates the OTP code entered by the user.
 * Call this when the user submits their OTP code.
 *
 * Expected request data: { email: string, otp: string }
 * Returns: { customToken: string }
 * Throws: HttpsError for validation failures
 */
export const validateOTP = onCall({}, async (req) => {
  const { email, otp: userOtp } = req.data;

  // Validate the OTP code
  // This will check if the code is correct, not expired, and hasn't exceeded max attempts
  return otp.validate(sharedConfig)(email, userOtp);
});

/**
 * Endpoint 3: Periodic Cleanup (Optional)
 *
 * This endpoint cleans up expired OTP documents from Firestore.
 * Use this as a scheduled function (cron job) to maintain database hygiene.
 *
 * Expected request data: none
 * Returns: { deletedCount: number }
 */
export const cleanupExpiredOTPs = onSchedule("every 24 hours", async () => {
  // Clean up expired OTP documents every 24 hours
  return otp.periodicCleanup(sharedConfig)();
});

// Alternative: HTTP callable cleanup endpoint for manual/custom scheduling
export const cleanupExpiredOTPsManual = onCall({}, async () => {
  return otp.periodicCleanup(sharedConfig)();
});

Endpoint Flow

  1. User enters email → Call initializeOTPSignIn

    • Generates a random OTP code (default 8 characters)
    • Creates user if they don't exist
    • Stores OTP hash securely in Firestore with expiration
    • Sends email with the OTP code
    • Returns: { newUser: boolean, otpTTL: number, expiresAt: Timestamp }
  2. User enters OTP code → Call validateOTP

    • Validates the OTP against stored hash
    • Checks expiration and attempt limits
    • Sets user's emailVerified to true on success
    • Generates Firebase custom token for authentication
    • Returns: { customToken: string }
    • Throws HttpsError on validation failures (expired, invalid, max attempts)
  3. Scheduled cleanupcleanupExpiredOTPs (runs automatically)

    • Queries for all expired OTP documents in Firestore
    • Batch deletes expired documents
    • Returns: { deletedCount: number }
    • Recommended: Run every 6-24 hours to maintain database hygiene

Template Variables in Email

Email templates support dynamic content using template variables:

  • {otp} - The generated OTP code (e.g., "123456")
  • {email} - The recipient's email address (e.g., "[email protected]")

Example:

subjectTemplate: "Your {otp} code for MyApp";
// Becomes: "Your 123456 code for MyApp"

htmlTemplate: "Hi {email}, your code is <b>{otp}</b>";
// Becomes: "Hi [email protected], your code is <b>123456</b>"

Template Tips:

  • Use {otp} in the subject line for easy identification
  • Include {email} for personalization
  • Provide both HTML and text templates for better compatibility
  • Keep templates clear and include expiration information

Configuration Options

OTPConfigCommon
  • app: Firebase Admin App instance
  • firestoreCollectionPath: Firestore collection path for storing OTP data
OTPConfigInitialize (extends OTPConfigCommon)
  • saltRounds: Number of salt rounds for bcrypt hashing
  • maxSignInAttempts: Maximum number of sign-in attempts allowed
  • otpLength: Length of the generated OTP code
  • otpTTL: Time-to-live for OTP in seconds
  • customOtpGenerator: Optional custom OTP generator function
  • nodeMailerConfig: Email configuration object
NodeMailer Configuration
nodeMailerConfig: {
  smtp: {
    host: "your-smtp-host",
    port: 587,
    auth: {
      user: "your-username",
      pass: "your-password"
    }
  },
  email: {
    from: '"Sender Name" <[email protected]>',
    subjectTemplate: "Your OTP is {otp}",
    htmlTemplate: "Your OTP: <b>{otp}</b>",
    textTemplate: "Your OTP: {otp}"
  }
}

Template Variables

Email templates support the following variables:

  • {otp}: The generated OTP code
  • {email}: The recipient's email address

Methods

  • otp.initialize(config) - Initializes OTP generation and sends email
  • otp.validate(config) - Validates an OTP code
  • otp.configureLogger(level) - Sets logging level ("verbose", "info", "warn", "error")
  • otp.periodicCleanup(config) - Cleans up expired OTP records

Import Options

// Default import
import { otp } from "@grace-studio/firebase-server";

// Type imports
import {
  OTPConfigCommon,
  OTPConfigInitialize,
  LogLevel,
} from "@grace-studio/firebase-server";

For React utilities, install the separate package:

npm install @grace-studio/firebase-react  # Coming soon

Development

# Install dependencies
npm install

# Build the package
npm run build

# Clean build artifacts
npm run clean

Publishing

# Version and publish beta
npm run version:beta
npm run publish:beta

License

ISC