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

firevault-js

v1.0.3

Published

A Mongoose-inspired Firestore object modeling library to make life easier.

Downloads

10

Readme

Firevault

Firevault is a Mongoose-inspired Firestore object modeling tool to make life easier.

Installation

Use the package manager npm to install Firevault.

npm install firevault-js

Importing

// Using Node-js
const firevault = require('firevault-js');

// Using ES6 imports
import firevault from 'firevault-js';

Connection

You can connect to Firevault using the Firestore service imported from Firebase Admin SDK.

import { initializeApp } from 'firebase-admin/app';
import { getFirestore } from 'firebase-admin/firestore';
import { initDB } from 'firevault-js';

initializeApp();

initDB(getFirestore());
import admin from 'firebase-admin';
import { initDB } from 'firevault-js';

admin.initializeApp();

initDB(admin.firestore());

If needed, you can retrieve the same instance of the Firestore service using 'getDB'.

import { getDB } from 'firevault-js';

const db = getDB();

Types

Firevault supports following data types:

  • String: string
  • Number: number (integer or float)
  • Boolean: boolean
  • Object: Javascript object
  • Array: Javascript array

Schema

The Schema constructor has 2 parameters.

  • Schema Definitions - Each Key in the schema can have the following properties:
    • type: A type from Firevault SchemaTypes.
    • required (optional): Boolean indicating if the field is required, or an Array containing a Boolean indicating if the field is required, followed by a String, which serves as the error message to display in case check fails.
    • default (optional): A Function that returns a default value.
    • validate (optional): A Function (which accepts value as a parameter) which returns a Boolean, or an Array of 2 values - first value is the check to be carried out (a Function which accepts value as a parameter), second value is a String containing an error message for when check fails.
    • maxLength (optional): A Number, or an Array of 2 values - first value is the limit, second value is a String containing an error message for when check fails.
    • minLength (optional): A Number, or an Array of 2 values - first value is the limit, second value is a String containing an error message for when check fails.
    • transform (optional): A custom method to be carried out to the parsed value.
    • schema (optional): Use this field if type is an Object, and you'd like to define its nested fields.
    • arrayOf (optional): If type is an Array, this specifies the type of values inside. If the type is not an Array, this attribute should be omitted.
  • Methods (optional):
    • beforeSave: A method to be executed before each save to Firestore.
import { Schema, SchemaTypes } from 'firevault-js';
import validator from 'validator';
import bcrypt from 'bcrypt';

const { String, Number, Boolean, Array } = SchemaTypes;

const userSchema = new Schema({
  name: {
    type: String,
    required: true,
    transform: (value) => value.charAt(0).toUpperCase() + value.slice(1)
  },
  email: {
    type: String,
    required: [ true, 'Email address is required' ],
    validate: [ validator.isEmail, 'Please enter a valid email address' ],
    transform: (value) => value.toLowerCase()
  },
  password: {
    type: String,
    required: true
  },
  details: {
    type: Object,
    default: () => { return {} },
    schema: {
      address: {
        type: String,
        default: () => '',
        validate: [ 
          (value) => value.match('^[A-Za-z0-9]+$'), 
          'An address can only contain letters and numbers' 
        ]
      },
      skills: {
        type: Array,
        arrayOf: String,
        minLength: [ 1, 'Please enter at least 1 skill' ],
        maxLength: [ 5, 'You can only have up to 5 skills' ]
      },
      isAdmin: {
        type: Boolean,
        required: true,
        default: () => false
      }
    }
  },
  createdAt: {
    type: Number,
    default: () => Date.now()
  }
}, {
  beforeSave: async (data) => {
    if (data.password) {
      const salt = await bcrypt.genSalt(10);
      data.password = await bcrypt.hash(data.password, salt);
    }
  }
});

Model

You can create a model from the schema. It requires 2 parameters.

  • collection: String value for the Firestore collection
  • schema: An instance of Schema.
import { Model } from 'firevault-js';

const User = new Model("users", userSchema);

Usage

Model object has following methods:

create

This method creates a document in the respective Firestore collection.

Requires

  • data: An object of the data to be stored in Firestore

Returns

  • A promise of the data stored in the Firestore collection
const data = await User.create({
  name: "johnny davis", 
  email: "[email protected]", 
  password: "123456",
  details: {
    skills: ["coding"]
  }
});
/*
{
  id: 'IKbgSBsj0pPsq5OyCgjU',
  name: 'Johnny Davis',
  email: '[email protected]',   
  password: '$2a$10$FKgf3mILGVZEr6qWbhFMEOAAOjJle5EBQniqJmrs1scruRgF/i8qu', 
  details: {
    address: '',
    skills: ["coding"],
    isAdmin: false
  }       
  createdAt: 1659555047599
}
*/

Optional

  • options: An object containing 4 properties
    • id: A string which can be used as an ID of the newly created document. If omitted, Firestore will automatically generate one. Defaults to undefined.
    • skipValidation: A boolean which can disable the validation before adding document to Firestore. Defaults to false.
    • skipFormatting: A boolean which can disable formatting and return the document reference, instead of the formatted object. Defaults to false.
    • skipStrip: A boolean which can disable the automatic removal of data properties which are not defined in the schema. Defaults to false.
const data = await User.create({
  name: "johnny davis", 
  email: "[email protected]", 
  password: "123456",
  details: {
    skills: ["coding"]
  }
}, { id: 'custom-id', skipValidation: true });
/*
{
  id: 'custom-id',
  name: 'johnny davis',
  email: '[email protected]',   
  password: '123456',   
  details: {
    skills: ["coding"]
  }     
}
*/
const data = await User.create({
  name: "johnny davis", 
  email: "[email protected]", 
  password: "123456",
  details: {
    skills: ["coding"]
  }
}, { skipFormatting: true });
/*
{
  id: 'IKbgSBsj0pPsq5OyCgjU',
  firestore: ...,
  parent: ...,   
  path: ...,
  ...
}
*/

findById

This method returns a single document from the collection.

Requires

  • id: id of the document

Returns

  • Promise of the data from collection
const data = await User.findById('IKbgSBsj0pPsq5OyCgjU');
/*
{
  id: 'IKbgSBsj0pPsq5OyCgjU',
  name: 'Johnny Davis',
  email: '[email protected]',   
  password: '$2a$10$FKgf3mILGVZEr6qWbhFMEOAAOjJle5EBQniqJmrs1scruRgF/i8qu', 
  details: {
    address: '',
    skills: ["coding"],
    isAdmin: false
  }       
  createdAt: 1659555047599
}
*/

Optional

  • options: An object containing 1 property.
    • skipFormatting: A boolean which can disable the formatting and will return a single document snapshot from the collection, instead of the formatted object. Defaults to false.
const data = await User.findById('IKbgSBsj0pPsq5OyCgjU', { skipFormatting: true });
/*
{
  id: 'IKbgSBsj0pPsq5OyCgjU',
  exists: true,
  metadata: ...,   
  ref: ...,
  ...
}
*/

find

This method can be used to get one or more documents from Firestore. You can use following methods with find.

  • where: Specifying conditions.
  • orderBy: Ordering data by a field.
  • limit: Limiting total documents returned from Firestore.
  • limitToLast: Limiting total documents returned from Firestore, starting from the end (must specify at least one "orderBy" clause).
  • startAfter: Find documents that start after the provided document (exclusive).
  • endBefore: Find documents that end before the provided document (exclusive).
  • offset: Offset on the data returned from Firestore.
  • get (async): This method is required at the end of each query with find in order to execute the query. It returns a Promise with the found documents.
    • options (optional) - An object containing 1 property.
      • skipFormatting - A boolean which can disable formatting and return a query snapshot, instead of the formatted documents.
  • count (async): This method returns a Promise which resolves with the number of documents which match the query.

Differtent usages of this method are as following:

// returns all the  posts in collection
const posts = await Post.find().get();
/*
[
  {
    id: 'qXdmXL1ebnE2aAMRJLBt',
    user: { id: 'IKbgSBsj0pPsq5OyCgjU' },
    createdAt: 2022-07-20T18:17:54.456Z, 
    updatedAt: 2022-07-20T18:17:54.456Z, 
    content: 'This is a test post',      
    title: 'Hello World 2'
  },
  {
    id: 'zHsHFjSQ0MCcrIgnilN1',
    user: { id: 'NLQklOyIeP6FChAPtMck' },
    title: 'Hello World',
    createdAt: 2022-07-20T16:16:14.882Z,
    updatedAt: 2022-07-20T18:38:35.018Z,
    content: 'Updated content'
  }
]
*/
// returns conditional (unformatted) data
const data = await Post
  .find()
  .where('user.id', '==', 'IKbgSBsj0pPsq5OyCgjU')
  .orderBy('createdAt', 'desc')
  .limit(2)
  .offset(1)
  .get({ skipFormatting: true });
/*
{
  docs: [{...}],
  empty: false,
  metadata: ...,   
  size: 1,
  ...
}
*/
// returns number of documents matching the query
const data = await Post
  .find()
  .where('user.id', '==', 'IKbgSBsj0pPsq5OyCgjU')
  .orderBy('createdAt', 'desc')
  .count();
/*
1
*/

updateById

This method can be used to update the content of an existing document in collection.

Requires

  • id: Id of the document
  • data: Data to be updated

Returns

  • Promise of the id
const data = await User.updateById('IKbgSBsj0pPsq5OyCgjU', { 
  email: '[email protected]' 
});
/*
IKbgSBsj0pPsq5OyCgjU
*/
const data = await User.updateById('IKbgSBsj0pPsq5OyCgjU', { 
  'details.isAdmin': true 
});
/*
IKbgSBsj0pPsq5OyCgjU
*/

Optional

  • options: An object containing a 2 property
    • skipValidation: A boolean which can disable the validation before updating document in Firestore. Defaults to false.
    • skipStrip: A boolean which can disable the automatic removal of data properties which are not defined in the schema. Defaults to false.
const data = await User.updateById(
  'IKbgSBsj0pPsq5OyCgjU', 
  { 
    'details.skills': [] 
  }, 
  { 
    skipValidation: true 
  }
);
/*
IKbgSBsj0pPsq5OyCgjU
*/

deleteById

This method can be used to delete an existing document in collection.

Requires

  • id: Id of the document

Returns

  • Promise of the id
const data = await User.deleteById('IKbgSBsj0pPsq5OyCgjU');
/*
IKbgSBsj0pPsq5OyCgjU
*/

validate

This method validates input data based on schema rules.

Requires

  • data: An object of the data to be validated

Returns

  • A promise of the validated data
const data = await User.validate({
  isAdmin: true,
  skills: ["coding"]
});
/*
{
  isAdmin: true,
  skills: ["coding"]
}
*/

Optional

  • options: An object containing 4 properties
    • skipRequired: A boolean which can skip the required check. Defaults to true.
    • skipDefault: A boolean which can skip the default function. Defaults to true.
    • skipStrip: A boolean which can disable the automatic removal of data properties which are not defined in the schema. Defaults to false.
    • allowDotNotation: A boolean which can allows data properties which contain dot notation (e.g. { "foo.bar": "foobar" }) to be converted to nested properties (e.g. { "foo": { "bar": "foobar" } }), check against the schema, and then convert back to dot notation strings. Defaults to true.
const data = await User.validate({
  "details.bio": "Experience web developer"
});
/*
{}
*/
const data = await User.validate({
  "details.bio": "Experience web developer"
}, { skipStrip: true });
/*
{
  "details.bio": "Experience web developer"
}
*/

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

License

MIT