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 🙏

© 2025 – Pkg Stats / Ryan Hefner

pring-admin

v1.0.0

Published

Cloud Firestore model framework for TypeScript - Google

Readme

Pring Admin

Firebase Cloud Firestore model framework for TypeScript.

Installation ⚙

npm add pring-admin

Usage

TypeScript

required

  "devDependencies": {
    "@types/node": "^10.9.2",
    "typescript": "^3.0.3"
  },

tsconfig.json

For Firebase CloudFunctions

{
  "compilerOptions": {
    "lib": ["es2018", "dom"],
    "module": "commonjs",
    "noImplicitReturns": true,
    "outDir": "lib",
    "experimentalDecorators": true,
    "sourceMap": true,
    "target": "es2018"
  },
  "compileOnSave": true,
  "include": [
    "src"
  ],
  "exclude": [
    "node_modules"
  ]
}

For Admin

import * as admin from 'firebase-admin'
import * as Pring from 'pring'

const app = admin.initializeApp()

Pring.initialize(app.firestore())

Scheme

  • Use @property annotation for property declaration.

SubCollection can not be optional. Initialise it as show below:

import * as Pring from "pring"
const property = Pring.property

class Group extends Pring.Base {
    @property name: string
    @property users: NestedCollection<User> = NestedCollection(this)
}

class User extends Pring.Base {
    @property name: string
    @property groups: ReferenceCollection<Group> = ReferenceCollection(this)
}

Manage data

Initialize


// auto generate ID
let user = new User()

// any ID
let user = new User("YOUR_ID")

// any ID, Handle already saved users
let user = new User("YOUR_ID", {})

memo

The developer is responsible for managing the Document being saved. In Pring it is prohibited to save the already saved Document again.

Please use explicitly by the initialization method. new User("YOUR_ID", {}) let user = new User("YOUR_ID")

Save

let user = new User()
user.name = "hoge"
await user.save()

Get

let user: User = await User.get("USER_ID", User)

Update

let user: User = await User.get("USER_ID", User)
user.name = "UPDATE NAME"
await user.update()
let user: User = new User("USER_ID", {})
user.name = "UPDATE NAME"
await user.update()

Delete

let user: User = await User.get("USER_ID", User)
await user.delete()

SubCollection

You can use ReferenceCollection and NestedCollection. The inserted Object is saved simultaneously with the save of the parent.

let user = new User()
let group = new Group()
user.groups.insert(group)
await user.save()

If you insert the parent after it is saved, you need to use await to guarantee the count of SubCollection.

let user = new User()
await user.save()

let group0 = new Group()
let group1 = new Group()
try {
  await user.groups.insert(group0)
  await user.groups.insert(group1)
} catch(error) {
  console.log(error)
}

DataSource

DataSource is a class that controls Collection of Firestore.

export default class Home extends Vue {

  public async addUser() {
    const user: User = new User()
    user.name = "@1amageek"
    await user.save()
  }

  public created() {
    const dataSource = User.query().dataSource(User)
    dataSource.on((snapshot, changes) => {

      switch (changes.type) {
        case "initial": {
          console.log(dataSource.documents)
          break
        }
        case "update": {
          console.log("insert", changes.insertions)
          console.log("change", changes.modifications)
          console.log("delete", changes.deletions)
          break
        }
        case "error": {
          break
        }
      }
    }).listen()
  }
}

Test

Setup

You have three options for running tests:

  1. Using Firebase Emulator (Recommended):

    # Install Firebase CLI
    npm install -g firebase-tools
       
    # Start Firestore Emulator
    firebase emulators:start --only firestore
       
    # In another terminal, run tests
    export FIRESTORE_EMULATOR_HOST=localhost:8080
    jest
  2. Using a Firebase service account key:

    • Go to Firebase Console → Project Settings → Service Accounts
    • Click "Generate new private key"
    • Save the downloaded JSON file as key.json in the project root
  3. Using environment variable:

    export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-key.json"

Running Tests

npm install -g jest 
# With emulator (recommended)
export FIRESTORE_EMULATOR_HOST=localhost:8080
jest

# With credentials
jest

Note: If no credentials are provided, tests will automatically attempt to use the Firestore Emulator at localhost:8080.