Skip to content

JMPSequeira/strongstore

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

StrongStore

 

What it is?

StrongStore is a type wrapper for firebase 9 web sdk, specifically targeting the firestore module redeclaring the necessary functions in order to provide a typed firestore.

It allows for autocomplete and type checking based on a simple configuration.

 

Installation Guide


 

  • Install the firebase package dependency:
    $ npm install firebase@9
    
  • Install the strongstore package:
    $ npm install -D strongstore
    

 

Configuration


 

StrongStore redeclares functions in 'firebase/firestore' so if you compile with '--skipLibCheck false' it will throw a redeclare error for each one of those functions.

 

  • Import StrongStore into a declaration (d.ts) file (I personally call it data.d.ts):
    import "strongstore";

 

Modes

 

StrongStore works in two mutually exclusive ways: Typed or Strict.

 

Typed Mode (No extra configuration needed)

 

  • Simply use firebase as you'd normally do:
    import { collection, getDocs, getFirestore, orderBy, query, where } from 'firebase/firestore';
  • Import your document models:
    /* 
        interface City { name:string; mayor: Person; } 
        interface Person { name:string; nicknames: string[]; } <- a nested object
    */
    
    import { City } from '/models/city';
  • Enjoy the features provided: drawing

 

Strict Mode

  Strict Mode relies on a declared global type called FirestoreConfig. If it does not exist it defaults to Typed Mode. Strict Mode is ...strict. Only configured collections will work.

  • Import your data models in the same file you imported StrongStore:

    /* 
        interface City { name:string; }
    
        interface Attraction { type: "Park" | "Station" | "Monument"}
    */
    
    import { City } from '/models/city';
    import { Attraction } from '/models/attraction';
  • Declare FirestoreConfig in global declaration:

    declare global {
        type FirestoreConfig = {
            cities: City;
            ["cities/attractions"]: Attraction; // <- to express a sub collection
        }
    }
  • All features from Typed Mode will work but now instead of casting you'll pass a path to a collection or document and it will resolve a:

    • MappedCollection<T, Key> (extends CollectionReference)
    • or MappedDocument<T, Key> (extends DocumentReference):
    const firestore = getFirestore();
    
    //      ↓ MappedCollection<City, "cities">
    const citiesCollection = collection(firestore,"cities");
    
    //      ↓ MappedDocument<City, "cities">
    const nyDoc = doc(firestore,"cities/NY");
    
    //      ↓ MappedCollection<City, "cities">
    const citiesCollection = nyDoc.parent;
    
    //      ↓ null
    const nullParent = citiesCollection.parent;
  • Besides the explicit path, you can use:

    //      ↓ MappedCollection<Attraction, "cities/attractions
    const nyAttractions = collection(firestore,"cities", "NY", "attractions");
    //      is the same as
    const nyAttractions = collection(cities,"NY/attractions");
    //      is the same as
    const nyAttractions = collection(cities,"NY", "attractions");
    //      is the same as
    const nyAttractions = collection(cities,"NY/", "/attractions"); // <= trims leading and trailing '/'
    //      is the same as
    const nyAttractions = collection(nyDoc,"attractions");
  • You can even use string templates, or variables, for path segments:

    • For collection segments, as long as it's resolvable to a compile time constant:
    const citiesPath = "cities";
    //      ↓ MappedCollection<Attraction, "cities/attractions
    const nyAttractions = collection(firestore,citiesPath, "NY", "attractions");
    //      is the same as
    const nyAttractions = collection(firestore,`${citiesPath}/NY/attractions`);
    • For document segments:
    // BE CAREFUL NOT TO PASS A SLASH
    function getNyCityAttractions(id: string) : Promise<QuerySnapshot<Attraction>> {
      
      //      ↓ MappedCollection<Attraction, "cities/attractions
      const nyAttractions = collection(firestore,"cities", id, "attractions");
      //      is the same as
      const nyAttractions = collection(firestore,`cities/${id}/attractions`);
    
      return getDocs(nyAttractions);
    }
    
    function getNyCityAttractions(union: "NY" | "LA") : Promise<QuerySnapshot<Attraction>> {
      
      //      ↓ MappedCollection<Attraction, "cities/attractions
      const nyAttractions = collection(firestore,"cities", union, "attractions");
      //      is the same as
      const nyAttractions = collection(firestore,`cities/${union}/attractions`);
    
      return getDocs(nyAttractions);
    }

About

A type wrapper for firebase/firestore 9 web sdk.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published