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

firestore-eloquent

v1.6.6

Published

A library for creating eloquent models in firestore.

Downloads

11

Readme

firestore-eloquent

A library for creating eloquent models in firestore inspired heavily by Laravel's Eloquent ORM.

tested with jest jest

Setup

Installation

npm:

npm install firestore-eloquent

yarn:

yarn add firestore-eloquent

Usage

Note: Firebase must be initialized before using these models.

Example:

const app = firebase.initializeApp({
  apiKey: "AIza....",
  appId: "1:27992087142:web:ce....",
  projectId: "my-firebase-project",
  authDomain: "YOUR_APP.firebaseapp.com",
  databaseURL: "https://YOUR_APP.firebaseio.com",
  storageBucket: "YOUR_APP.appspot.com",
  messagingSenderId: "123456789",
  measurementId: "G-12345",
});

If you have an already existing firestore instance:

import { setFirestore } from 'firestore-eloquent';

const firestore = app.firestore();

setFirestore(firestore);

You can also get the firestore instance that is being used:

import { getFirestore } from 'firestore-eloquent';

// returns firebase.firestore.Firestore
const firestore = getFirestore();

Making Models:

Using and creating models should be similar to using Laravel Eloquent Models.

Notes:

  • The Authenticatable class for user models is still under development.
  • It's possible to not override the constructor of the class, the library will try to infer the collection name according to the name of the class (ex: model Post will have a collection name of post). But this is not recommended because building a production version of an app that is using this library will most likely rename these classes due to minification of the code from webpack or other module bundlers.
import { Model, ModelData } from 'firestore-eloquent';

// Optional
export interface PostData extends ModelData {
    title: string;
    description: string;
}

export class Post extends Model<PostData> {
    type = Post;

    constructor(data?: Partial<PostData>) {
        super(data);
        // explicitly set collection name
        this.name = 'posts';
    }
    
    protected fillable() {
        return ['title', 'description'];
    }
}

CRUD Examples:

import { Post } from 'path/to/models';

const post = new Post({
    title: 'My Title',
    description: 'My Description',
});

// You can also use fill() or forceFill()
post.fill({
    title: 'My Title',
    description: 'My Description',
});

// create
await post.create(); /* or */ post.create(data);

// update
await post.update(); /* or */ post.update(data);

// delete
await post.delete();

// save
await post.save(); /* or */ post.save(data);

// fetching
await post.all();

// get one
await post.first();

// find one by id
await post.findOne(id);

// Reading data

// get a specific key
console.log(post.get('title')) // My Title

// get all data
console.log(post.getData()) // { title: 'My Title', description: 'My Description' }

// set data
post.set('title', 'My New Title');

await post.save();

Events

Events are also supported.

Example:

export class Post extends Model<PostData> {
    type = Post;

    constructor(data?: Partial<PostData>) {
        super(data);
        this.name = 'posts';
    }

    protected fillable() {
        return ['title', 'description'];
    }

    // register events here
    protected booted() {
        this.creating((post) => {});
        this.created((post) => {});

        this.updating((post) => {});
        this.updated((post) => {});

        this.deleting((post) => {});
        this.deleted((post) => {});

        this.saving((post) => {});
        this.saved((post) => {});
    }
}

Relationships

Currently, only hasOne, hasMany and belongsTo are supported.

Example:

export class Post extends Model<PostData> {
    type = Post;

    constructor(data?: Partial<PostData>) {
        super(data);
        this.name = 'posts';
    }
    
    protected fillable() {
        return ['title', 'description'];
    }

    comments() {
        return this.hasMany(Comment);
    }
}

export class Comment extends Model<CommentData> {
    type = Comment;

    constructor(data?: Partial<CommentData>) {
        super(data);
        this.name = 'comments';
    }
    
    protected fillable() {
        return ['body'];
    }

    post() {
        return this.belongsTo(Post);
    }
}

const post = new Post(data);
await post.save();

// saving
post.comments().save(new Comment({
    body: 'My comment',
}));

// creating
const comment = await post.comments().create(data);

// fetching
const comments = await post.comments().getAll();

// loading
await post.load(['comments']);

Collections

Collections extend the Array class and has several methods added to it. Model.all() and hasMany relationships all return Collections of that model. Some of the methods are overriden to improve their functionality such as collection.includes(model) and collection.indexOf(model).

const posts = await new Post().all(); // Collection<Post>

// call methods from `Array`
const post = posts.pop();

post.set('title', 'Another Title');

// pushes the post if it does not exist, otherwise it replaces with it's index
posts.set(post);

// or do this instead
posts.replace(post)

// find by id
const newPost = posts.get(id);

// load relationships of all posts
await posts.load(['comments']);
const comments = posts.map(post => post.get('comments')); // CommentData[]

// turn into a normal `Array`
const array = posts.toArray();

JSON

Calling JSON.stringify on models will automatically call getData() on them, this applies to collections as well.

Observers and Listeners

There are wrapper methods available to make use of firestore's onSnapshot method.

import { listen, addListener, removeListener, clearListeners } from 'firestore-eloquent';

// add a listener
const handle = addListener(Post, (posts) => {
    console.log(posts) // Post[]
});

// remove a listener
removeListener(Post, handle);

// tell the library to actually start listening to onSnapshot methods
listen(Post)

// remove all registered listeners
clearListeners(Post)

Example in React

const [posts, setPosts] = useState<Post[]>([]);

useEffect(() => {
    const handle = addListener(Post, setPosts);
    listen(Post);

    return () => {
        removeListener(Post, handle);
    };
}, []);

Contributing

Contributions are welcome! Just fork the project and make a pull request.

License

This library is open-sourced software licensed under the MIT license.