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

@typeheim/orm-on-fire

v0.1.0

Published

Firestore ORM

Downloads

15

Readme

ORMOnFire is a powerful Firestore ORM.

Installation

Install package

# in backend
yarn add firebase firebase-admin firebase-tools

# in frontend
yarn add firebase 

yarn add @typeheim/orm-on-fire
# or
npm -i @typeheim/orm-on-fire

Setup ORMOnFire driver:

// sample for Node.JS
FirebaseAdmin.initializeApp({
    credential: FirebaseAdmin.credential.cert('my.key.json'),
    databaseURL: "https://my-db.firebaseio.com",
})
OrmOnFire.driver = FirebaseAdmin.firestore()

Easy entity declaration

To define entity you need to use @Entity or @Agregate decorators for simple and nested collections. Note both decorators will transform class name to kebab case - lowercase and split words with hyphens, like UserFiles < => user-files.

Then, each document field must be decorated with @Field, @MapField, @CreatedDateField, @UpdatedDateField or @DocRef(for document references) decorators. Sub-collections can be referenced by @CollectionRef decorator.

import {
    Agregate,
    Entity,
    Collection,
    CollectionRef,
    ID,
    Field,
    CreatedDateField,
    UpdatedDateField,
    MapField
} from '@typeheim/orm-on-fire'
import { CreatedDateField } from './Entity'

@Agregate()
export class User {
    @ID() id: string

    @Field() firstName: string

    @Field() lastName: string

    @Field() status: string

    @CollectionRef(UserFile) files: Collection<UserFile>
}

@Entity({ collection: 'user-files' })
export class UserFile {
    @ID() id: string

    @Field() name: string

    @MapField() properties: FileProperties

    @CreatedDateField() createdAt: Date

    @UpdatedDateField() createdAt: Date
}

class FileProperties {
    type: "image" | "doc"
}

Simple data fetching

import { Collection } from '@typeheim/orm-on-fire'

// with promise-like interface
let markus = await Collection.of(User).one('markus').get()

// with Rx interface
Collection.of(User).one('tom').get().subscribe((tom: User) => {
    tom.files.forEach((file: UserFile) => {
        // some cool stuff
    })
}) 

Powerful filtering

Using firestore operators

import { Collection } from '@typeheim/orm-on-fire'
const UsersCollection = Collection.of(User)

// Search using regular Firesotre operators
let activeUsers = await UsersCollection.all().filter(user => user.status.equal('active')).get()
let notActiveUsers = await UsersCollection.all().filter(user => user.status.notEqual('active')).get()
let adultUsers = await UsersCollection.all().filter(user => user.age.greaterThan(18)).get()

Test index search

To use text index search you first need to add text index hook Firebase function to your Firebase functions list for each colelction you want to be idndexed

import { TextIndex } from '@typeheim/orm-on-fire'
import * as functions from 'firebase-functions'
import * as FirebaseAdmin from 'firebase-admin'

FirebaseAdmin.initializeApp()

export const generateUserIndex = TextIndex(functions, FirebaseAdmin).forCollection('users')
                                                     .fields(['name', 'text'])
                                                     .buildTrigger()

Official functions deployment guide: Get started: write, test, and deploy your first functions

Once you deploy hooks, you can use index search as below:

// Note: text index search is case-insensitive 
let usersStartsWithAlex = await UsersCollection.all().useIndex(user => user.firstName.startsWith('Alex')).get()
let usersEndsWithLex = await UsersCollection.all().useIndex(user => user.firstName.endsWith('lex')).get()

NOTE: for now text index won't work with collection group queries. Support coming in next releases.

Filter scopes:

Commonly used filer conditions can be organized in named filter scopes for easy code reuse:

class UserScope {
    static active() {
        return (user: EntityFilter<User>) => {
            user.status.equal(1)
        }
    }
}

// fetch all active users
let activeUsers = await UsersCollection.all().filter(UserScope.active()).get()

Sub-collection queries:

For nested collections you don't need to fetch each document separately and can access required collection under specific document ID:

// fetch all PDF files from user suwth id "userId"
let userFiles = await UsersCollection.one('userId').collecction(UserFile).filter(UserFile.pdf()).get()

Group collection queries:

ORMOnFire support easy declaration of collection groups the same way as for regular collections.

// fetch all file attachments that exist in any collection and sub-collection
let attechments = await Collection.groupOf(Attachment).all().filter(Attachment.file()).get()