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

@geckou/firebase-client

v0.3.0

Published

Firebase client SDK wrappers (app init / Firestore CRUD / Storage) for web and React Native

Readme

@geckou/firebase-client

Firebase クライアント SDK の薄いラッパー。アプリの初期化・Firestore の CRUD / 購読・Storage の アップロードを、web(Next.js)と React Native(Expo)の双方から同じ形で呼べるようにする。

firebase は peerDependencies。利用側と同じインスタンスを共有するためで、 dependencies に入れると別インスタンスの Firebase App が生成され、認証状態が共有されない。

各モジュールは 'use client' を持つ。Next.js App Router のサーバーコンポーネントから 直接 import するとビルドエラーになるので、クライアントコンポーネント経由で使う。

配布形式(ESM / CJS)

import すると ESM(dist/esm/)、require すると CJS(dist/)が読まれる。

ESM のビルドが要るのは、利用側と firebase SDK の実体を揃えるため。 このパッケージが require('firebase/firestore') で掴む実装と、アプリが import で掴む実装は、firebase 側の exports の条件分岐によって別物になる。firebase は db / auth を instanceof で検査するため、 CJS で作った db を ESM 側の doc() に渡すと Expected first argument to collection() to be a CollectionReference, a DocumentReference or Firebase Firestore で弾かれる(#66)。

そのため、initFirebase が返した app / auth / db は、アプリが直接 import した firebase/auth・firebase/firestore の API(runTransaction・writeBatch など、 ラッパーが持たないもの)にそのまま渡せる。

インストール

yarn add @geckou/firebase-client firebase

初期化

環境変数の取得方法が web / mobile で異なるため、設定は呼び出し側から渡す。 React Native は initializeAuth + AsyncStorage による永続化が要るので、 Auth の生成もファクトリで差し替えられる。

import { initFirebase } from '@geckou/firebase-client'

export const { app, auth, db } = initFirebase({
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY!,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN!,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID!,
  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET!,
  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID!,
  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID!,
})
// React Native
import { getReactNativePersistence, initializeAuth } from 'firebase/auth'
import AsyncStorage from '@react-native-async-storage/async-storage'

initFirebase(config, (app) =>
  initializeAuth(app, { persistence: getReactNativePersistence(AsyncStorage) })
)

すでに初期化済みのアプリがあれば再利用するので、複数回呼んでも多重初期化にならない。 2 回目以降は createAuth も呼ばれず、初期化済みの Auth が返る。 getReactNativePersistence() は呼ぶたびに別のクラスを返すため、再度 initializeAuth を 呼ぶと auth/already-initialized で落ちる(Fast Refresh や複数モジュールからの呼び出し)。

再利用のため、2 回目以降に渡した config と createAuth は効かない。黙って別プロジェクトへ 読み書きするのを避けるため、次の 2 つは console.warn で知らせる。

| 警告 | 意味 | | --- | --- | | 既存アプリの projectId が config.projectId と違う | 渡した設定は適用されていない(テストで別プロジェクトを初期化済み、複数プロジェクト構成) | | このモジュールが createAuth を実行した記録が無いアプリに createAuth を渡した | 今回の createAuth は呼ばれず getAuth の Auth が返る。意図した永続化が効いていない可能性がある(createAuth を渡す呼び出しを最初に実行すること)。Fast Refresh でモジュールだけ作り直された場合など、既存 Auth が実際には永続化付きのこともある |

Firestore

コレクション名は引数で受け取る。1つの Firebase プロジェクトに複数環境を相乗りさせていて stg_users のような接頭辞が要る場合も、呼び出し側で解決する。

import {
  getDocument,
  queryDocuments,
  subscribeCollection,
} from '@geckou/firebase-client/firestore'

const result = await getDocument<Post>(db, 'posts', postId)
if (result.success) {
  // result.data は Post | null
}

書き込み・取得系は例外を投げず、{ success: true, data } / { success: false, error } を返す。

取得・購読が返す id は常に Firestore のドキュメント ID。ドキュメント本文に id フィールドを持たせている場合でも、そちらでは上書きされない。

| 関数 | 用途 | | --- | --- | | getDocument | 1件取得(存在しなければ data: null) | | queryDocuments | 条件・並び順・カーソル・件数を指定して取得。lastDoc を次ページのカーソルに使う | | createDocument | ID 自動採番で作成 | | setDocument | ID 指定で作成・上書き(merge 指定可) | | updateDocument | 部分更新 | | removeDocument | 削除 | | subscribeCollection | コレクションの購読。解除関数を返す | | subscribeDocument | 単一ドキュメントの購読。解除関数を返す |

購読系は onError を省略すると console.error にフォールバックする。 queryDocuments の cursor は購読では使われない(subscribeCollection は先頭から流す)。

Storage

import { uploadFile } from '@geckou/firebase-client/storage'

const { downloadUrl, path } = await uploadFile(
  app,
  `users/${uid}/avatar.png`,
  file,
  ({ progress }) => setPercent(progress)
)

uploadFile / deleteFile / getFileUrl / getFirebaseStorage を提供する。 アップロードは uploadBytesResumable を使い、progress は 0〜100 のパーセント。 0 バイトのファイルは転送するものが無いため progress: 100 を通知する。 アップロード自体の失敗と、完了後の URL 取得の失敗は、どちらも reject される。