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 🙏

© 2024 – Pkg Stats / Ryan Hefner

firesocket

v1.0.17

Published

A drop-in replacement for WebSocket using Firebase Realtime Database

Downloads

10

Readme

npm

FireSocket

A drop-in replacement for WebSocket using Firebase Realtime Database.

Examples

An example showing dynamically switching between FireSocket and WebSocket is in example/.

A full example is running at https://firesocketexample.appspot.com/.

Code changes

Before with WebSocket

server:

const express = require("express");
const ws = require("ws");
const app = express();
const wss = new ws.Server({server});

wss.on("connection", ws => ...

client:

const ws = new WebSocket(window.location.href.replace("http", "ws"));
ws.addEventListener("open", () => ...

Using FireSocket

server:

const firesocket = require("firesocket");
const express = require("express");
const app = express();
const wss = firesocket.Server.createFromCreds(databaseUrl, {app, firebaseConfig});

wss.on("connection", ws => ...

client:

const ws = new FireSocket(); // Args are ignored
ws.addEventListener("open", () => ...

Firebase setup

  • Run npm install firesocket
  • Install firebase cli
  • Set up Realtime Database security rules
    • Run firebase login
    • Run firebase init
      • Create new project or use existing project created in Console
      • Select Database
      • For security rules, use the path node_modules/firesocket/database.rules.json
      • Don't delete the existing file
    • Run firebase deploy --only database
  • Set up Authentication
    • https://console.firebase.google.com/u/0/project/_/authentication
    • Enable Anonymous, and/or another provider to allow for resumption of socket connection
  • Set up Admin Authentication using a Service Account
    • Open IAM Service accounts
    • Permissing needed is "Firebase Realtime Database Admin": roles/firebasedatabase.admin
    • If running in GCP, add admin policy to your default service account
    • OR
    • Create new service account, name i.e. "server", give admin policy
    • For non-GCP servers or local testing, create service account credentials and store it securely
      • gcloud iam service-accounts keys create .test-creds.json --iam-account [email protected]
      • set $env:GOOGLE_APPLICATION_CREDENTIALS=".test-creds.json"

App setup

  • On the web server, change WebSocket to FireSocket
    • require("firesocket")
    • (TODO split up browser part) If clients are browser-based, use firesocket.Server.createFromCreds factory to create Server.
    • The returned FireSocket.Server object is API-compatible with WebSocket.Server
  • Download the Firebase client public JSON config for web app
    • The web server is expected to serve this JSON at /firebase-config.json
    • (TODO API) the firesocket.Server helper will add this to your express server
  • Add the script /firesocket.js before your web app's logic
    • Replace WebSocket with FireSocket (constructor args are ignored)
    • The FireSocket object is API-compatible with WebSocket
    • (TODO API) the firesocket.Server helper will serve this script

Roadmap to release 1.0

  • Basic parity with ws functionality
    • ~~message~~
    • ~~send~~
    • ~~readyState~~
    • open waits until server connects
    • ~~close~~
  • ~~A/B testing source compatibility between FireSocket and WebSocket~~
  • ~~Server admin authentication, supporting example server app and cli~~
  • ~~Database read/write limitations on user/server~~
  • Server lib for wiping some/all message state
  • ~~Client authentication~~
    • ~~web~~
    • ~~cli~~
  • ~~Example express server setup with HTTP serving the script file~~
  • ~~npm limit files for pack release~~
  • ~~bot to update dependencies~~
  • ~~generate .d.ts prepack or something~~
  • set up CI/CD that builds/tests/publishes to npm
    • ~~running tests in Cloud Build~~
    • ~~Set up using separate project~~
    • ~~Link from here to README in spec doc~~
    • ~~npm badge~~
    • build badges
    • ~~Github status checks on build success~~
    • ~~https://medium.com/@Philmod/npm-release-automation-adb970e49066~~
  • firebase disconnect messages using onDisconnect
  • Get vs code typing for firesocket.Server working
  • Any TODOs left in README
  • Any TODOs left in code, maybe won't fix

Future improvements

  • [ ] Authentication is pluggable, so app can swap in email/SMS/OAuth sign-in
  • [ ] Generate type declarations instead of relying on cast to WebSocket

Testing

Run npm test to run all tests. This includes unit tests, and mock tests using the firebase emulator and a local WebSocket server. See spec/ for more information.

The example/ can be useful for manually debugging changes.

Motivation for client-server communication

WebSocket

The default client-server communication, and by far the fastest. It's pretty simple for a web game to just update state and issue questions based on player events.

Downsides:

  • Cheap hosting servers don't allow many simultaneous connections, if any
  • Messages are not persisted, so a server reboot will wipe out any app state

Firebase Database

Using Firebase Realtime Database, it is possible to emulate WebSocket messages.

This fixes both limitations:

  • Firebase is free for 100 connections users, with pay-as-you-go up to 200k.
  • When the server restarts it can event-source state from the database

Realtime Database was picked over Firestore because the average round trip latency of 600ms is fast enough to barely be noticed by users, while Firestore is noticeably slower at 1500ms. medium.com

Guide: Info on Data Model, Auth, Queues

Database Schema

Each game is composed of messages from server to client, and v/v.

Each firebase client listens for child_added on their message queue.

Here, user* is a userID from Firebase Authentication

user:
    userWQ3mVT:
        0: Message: Connected to Game
        1: Choice: New Game, Refresh
        2: Message: Cards
        3: Choice: Play Copper, Buy Copper
    user7f8pR:
        0: Message: Connected to Game
        1: Choice: New Game, Refresh, alice's game
server:
    userWQ3mVT:
        0: Name: alice
        1: Choice: New Game
        2: Start: Militia, Moat, ...
    user7f8pR:
        0: Name: bob
        1: Choice: Refresh