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

firebase-glacier

v0.7.6

Published

Specification and tools to document firebase projects

Downloads

11

Readme

#firebase-glacier Specification and tools to document firebase projects


##Usage

###To use as command line utility npm install -g firebase-glacier

firebase-glacier in the terminal will read ./glacier.yml and output at ./firebase_spec/

firebase-glacier init in the terminal will create ./glacier.yml and output an initial build at ./firebase_spec/

###To use as module npm install --save-dev firebase-glacier


##Motivations This project was born from my necessity of a better way to design and write firebase's database rules

I based the main idea of the project on swagger, which is an open standard to define language-agnostic interfaces to REST APIs. With glacier, I adapted this concepts and ideas to fit a firebase project

The objective of glacier is to work on a single document that can be processed to generate useful output: database rules, storage rules and even html showing relevant formatted information in a visually pleasant way

The document to work with is called glacier document


##glacier document specification

The language to write a glacier document is yaml.

It contains five main fields at its root:

  • glacier
  • info
  • auth
  • database
  • storage

glacier : Indicates the firebase-glacier version

info : Contains information relevant to the project users

auth : Contains the configuration options of the auth service

database : Contains the database rules design

storage : Contains the storage rules design


###Main fields breakdown

####glacier Indicates the firebase-glacier version

glacier: "0.2"

####info Contains information relevant to the project users

info:
    version: "0.0.0"
    title: MyApp API
    description: Reference to MyApp API
    termsOfService: terms
    license: Copyright 2016 MyApp
    config:
        web:
            apiKey: none
            authDomain: none
            databaseURL: none
            storageBucket: none
    glossary:
        User: A user that can be assigned one or more role
        Admin: A user with elevated privileges

####auth Contains the configuration options of the auth service

auth:
    methods:
        - email
        - google
        - facebook
        - anonymous
    oauthRedirectDomains:
        - localhost
    allowMultipleAccountsWithSameEmail: false

####database Contains the database rules design

database:
    /users:
        .read: true
        .indexOn:
            - email
            - name
            - lastname
            - birthdate
        /$uid:
            .write: "auth.uid === $uid"
            .validate: "newData.hasChildren(['email', 'name', 'lastname'])"
            /email:
                .validate: "newData.isString()"
            /name:
                .validate: "newData.isString()"
            /lastname:
                .validate: "newData.isString()"

####storage Contains the database rules design

Still to be defined


##Processors

At this point, the project counts with just the database rules processor. It'll read the glacier document and serialize the database field in json format and will be saved into a file ready to be imported to the firebase project.

To invoke all processors (database rules processor and storage rules processor, for now) just:

var glacier = require('firebase-glacier')
glacier.build()

It'll read the glacier document from ./firebase_spec/glacier.yml and output ./firebase_spec/database.rules.json and ./firebase_spec/storage.rules.json

###Database rules processor The database rules processor will ignore all metadata fields and remove the leading slashes from any child of the database root field and

var glacier = require('firebase-glacier')
glacier.buildDbRules()

###Storage rules processor Not implemented yet

###Html generator Not implemented yet


##Metadata The json document used to define rules in firebase says little about what they are meant for when you're not the one that designed those rules (unless you know how security rules work). For this reason, glacier reserves the $ character (at the start of the field) to define arbitrary metadata in the glacier document. A metadata field is meant to be used by a processor.

For example:

/messenger:
    $notes: Conversations messages record
    /$conversation:
        /members:
            $notes: Key sided object containing the uids of the conversation members
        /messages:
            /$key:
                /$uid:
                    $notes: Message owner
                /message:
                    .validate: "newData.isString()"

Here, we are defining $notes as a metadata field that explains what the parent field represents/does/etc. and can be used, say, by the html generator to show this notes to the reader in a stylized way.

Another one:

/users:
    /$uid:
	    /status:
		    $notes: Represent the current status of the user
		    $acceptedValues:
			    - Online
			    - Offline
			    - Suspended
			    - Banned

In this example we defined the $acceptedValues metadata field. This one can be used by the database rules processor to generate the .validate field using the array values instead of manually writing a cumbersome long string to accomplish that rule: (newData.val() === 'Online') || (newData.val() === 'Offline') || ... By the way, this feature is not implemented yet


##Middleware For the database rules processor, the registered middleware (can be more than one of course) is the first agent to handle the glacier document. Its input is an object representation of the glacier document. Its output must be the same object already processed. After every middleware is invoked, the database rules processor will continue its job

###Built-in middleware ####decorators This middleware allows to define arbitrary decorators that'll get replaced with the values they're associated. Decorators are defined as fields of a decorators field placed at the root of the glacier document. Currently, the use of decorators inside the definition of others decorators is not supported.

Example:

glacier: ...
info: ...
auth: ...
database: ...
storage: ...
decorators:
    owner: "auth.uid === $uid"
    client: "root.child('clients').hasChild(auth.uid)"
    admin: "root.child('admins').hasChild(auth.uid)"
    create: "(!data.exists() && newData.exists())"
    update: "(data.exists() && newData.exists())"
    delete: "(data.exists() && !newData.exists())"
    timestamp: "newData.val() === now"
    isString: "newData.isString()"
    starsRate: "(newData.val() === 1 || newData.val() === 2 || newData.val() === 3 || newData.val() === 4 || newData.val() === 5)"

Usage:

database:
    /users:
	    .read: true
	    /$uid:
		    .write: @owner
		    /email:
			    .validate: @isString
		    /name
			    .validate: @isString
		    /$other:
			    .validate: false
    /products:
	    .read: true
		/$key:
			.write: @admin
			/name:
				.validate: @isString
			/rating:
				/$uid:
					.write: @client
					/stars:
						.validate: @starsRate
					/$other:
						.validate: false
			/$other:
				.validate: false

####validate This middleware allows to define metadata that starts with "$validate" as a chunk of a ".validate" field. The ".validate" field gets generated by concatenating all "$validate..." fields. If defined, ".validate" is concatenated too. The OR operation is applied between the "$validate..." fields

Example:

database:
	/$something:
		/status:
			.write: true
			$validate_REQUESTING: "(!data.exists() && newData.val() === 'REQUESTING')"
			$validate_CANCELED: "(data.val() === 'REQUESTING' && newData.val() === 'CANCELED')"
			$validate_REJECTED: "(data.val() === 'REQUESTING' && newData.val() === 'REJECTED')"
			$validate_ACCEPTED: "(data.val() === 'REQUESTING' && newData.val() === 'ACCEPTED')"
			$validate_FINISHED: "(data.val() === 'ACCEPTED' && newData.val() === 'FINISHED')"

Example output:

database:
	/$something:
		/status:
			.write: true
			.validate: "(!data.exists() && newData.val() === 'REQUESTING') || (data.val() === 'REQUESTING' && newData.val() === 'CANCELED') || (data.val() === 'REQUESTING' && newData.val() === 'REJECTED') || (data.val() === 'REQUESTING' && newData.val() === 'ACCEPTED') || (data.val() === 'ACCEPTED' && newData.val() === 'FINISHED')"