Compact firebase client implementation for NodeJS environment
Requires Node.js >= 20.19.
npm install @eneris/firebase-nodejs-clientyarn add @eneris/firebase-nodejs-clientCurrent official modules support only
- Node.js as Admin with few to no client capabilities
- Browser only env (hard linked to
window,IndexedDBandWebWorkers)
I needed a module that I could use in any JavaScript environment. The main difference is that you can provide your own storage with simple get/set methods for data persistence.
Putting this public, so it can help some other projects too. Will add more parts based on my project needs or upon request.
- ✅ Web Installations
- ✅ Mobile Installations
- ✅ Remote config
- ✅ Cloud Messaging - receiving push notifications (
PushReceiver) - ✅ Cloud Messaging - sending push notifications (
PushSender) - ✅ Google Analytics 4 events (
Analytics) - ✅ HeartBeat
- ✅ Reliability tests using the Node.js test runner
| Export | Description |
|---|---|
FirebaseApp |
Shared app instance holding credentials, storage, logger and crypto |
Installations |
Firebase Installations (FID + auth token) and heartbeat header |
InstallationsRequestError |
Thrown by Installations methods on a non-ok FIS response, carries status |
RemoteConfig |
Remote config fetch/activate with auto refresh (also the default export) |
Value |
Remote config value returned by getValue/getAll, with typed getters |
Analytics |
GA4 event logging through the g/collect endpoint |
PushReceiver |
Persistent MCS/FCM connection receiving push notifications |
PushSender |
Sending push notifications via the FCM HTTP v1 API |
PushReceiverLegacy |
Drop-in compatible API for @eneris/push-receiver consumers |
const fs = require('fs')
const path = require('path')
const { FirebaseApp, Installations, RemoteConfig } = require('@eneris/firebase-nodejs-client')
const storageFileName = path.join(__dirname, 'storage.json')
let store = {}
if (fs.existsSync(storageFileName)) {
store = JSON.parse(fs.readFileSync(storageFileName).toString())
}
const app = new FirebaseApp({
credentials: { /* CREDENTIALS HERE */ },
storage: {
get: (key) => store[key],
set: (key, value) => {
store[key] = value
fs.writeFileSync(storageFileName, JSON.stringify(store, null, 2))
}
}
})
const remoteConfig = new RemoteConfig(app, {
defaultConfig: {
test: 'true'
}
})
remoteConfig.on('fetch', () => {
console.log('fetch')
})
remoteConfig.on('activate', () => {
console.log('activate')
})
remoteConfig.fetchAndActivate().then(() => {
console.log(remoteConfig.getAll())
})Every module namespaces its own keys inside the provided storage, so a single storage instance can be shared by all of them. See FirebaseApp for all available options.
PushReceiver registers the app with GCM/FCM, keeps a persistent connection to mtalk.google.com open, decrypts incoming messages and deduplicates them using persistent ids stored in your storage. Registration data is persisted, so a restarted process reuses the same FCM token.
// Second argument is the push identity config (bundleId, chrome identity, timeZone, vapidKey).
// Every field is optional and falls back to its DEFAULT_* value, but the object itself is required.
const client = new PushReceiver(app, {})
client.onNotification(({ message, persistentId }) => {
console.log('Notification received', persistentId, message)
})
await client.connect()
console.log('FCM token:', client.fcmToken)Migrating from @eneris/push-receiver? Use PushReceiverLegacy, which keeps the old config and credentials shape.
PushSender sends messages through the FCM HTTP v1 API using your service account.
const sender = new PushSender({ /* SERVICE ACCOUNT JSON HERE */ })
await sender.send({ title: 'Hello', body: 'World' }, fcmToken)Analytics sends GA4 events to the same g/collect endpoint gtag.js uses, so no api_secret is needed.
const analytics = new Analytics({ app })
await analytics.logEvent('page_view', { page_title: 'Home' })example/fetch.js- remote configexample/push.js- push receiver + senderexample/analytics.js- analytics events
- Big thanks to authors of https://github.com/firebase/firebase-js-sdk . Most of the logic/types/infromation comes from there
- Push receiving logic originates from https://github.com/Eneris/push-receiver