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

firefuncs

v1.0.3

Published

Create Firebase Cloud Functions from functions marked with decorators

Downloads

10

Readme

firefuncs

Create Firebase cloud functions from Typescript functions marked with decorators.

NPM version

npm i firefuncs

To demonstrate the use of firefuncs, let's create Firebase cloud functions with and without firefuncs.

Creating Firebase cloud functions without firefuncs

For a start you may have all your cloud functions in one file.

index.ts

import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';

exports.helloWorld = functions.https.onRequest((request, response) => {
 response.send('Hello from Firebase!\n\n');
});

exports.initializeApp = functions.https.onRequest(async (request, response) => {
 admin.initializeApp(functions.config().firebase);
});

Over time that file grows and that necessitates breaking it into smaller files. You may do so as shown below.

hello.functions.ts

import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';

export const helloWorld = (request, response) => {
 response.send('Hello from Firebase!\n\n');
};

export const initializeApp = async (request, response) => {
 admin.initializeApp(functions.config().firebase);
};

index.ts

// import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';
import { helloWorld, initializeApp } from './hello.functions';

exports.helloWorld = functions.https.onRequest(helloWorld);

exports.initializeApp = functions.https.onRequest(initializeApp);

While this is a lot better than the first example, it still requires that index.ts be modified every time new functions are added or existing ones removed.

To get a solution where index.ts never needs to change even as functions are added or removed, we need a way of specifying what a function is meant for; we need a way of marking or decorating a function with its purpose. Enter decorators!

Creating Firebase cloud functions using firefuncs

firefuncs makes use of decorators, an experimental TypeScript feature. Ensure you enable experimentalDecorators and emitDecoratorMetadata options in tsconfig.json.

{
  "compilerOptions": {
    /* Other Options */

    /* Experimental Options */
    "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    "emitDecoratorMetadata": true         /* Enables experimental support for emitting type metadata for decorators. */
  }
}

Install firefuncs

npm i firefuncs

Move your functions into classes and decorate them with the appropriate decorators. In the example below, we want our functions to handle HTTP requests, so we decorate them with the onHttpsRequest decorator.

functions/hello.functions.ts

import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';
import { func, onHttpsRequest } from 'firefuncs';

export class Hello {
    @func()
    @onHttpsRequest()
    public helloWorld(request, response) {
        response.send('Hello from Firebase!\n\n');
    }

    @func()
    @onHttpsRequest()
    public initializeApp(request, response) {
        admin.initializeApp(functions.config().firebase);
    }
}

To create cloud functions, use the getFunctions function from firefuncs, supplying a glob pattern that matches all the files containing TypeScript class methods that should be converted to Firebase cloud functions.

index.ts

import { getFunctions } from 'firefuncs';

// search the 'functions' directory and all its subdirectories
// for JavaScript or TypeScript files
const funcs = getFunctions(__dirname + '/functions/**/*.{js,ts}');

// loop through the keys in 'funcs'
// and assign their values to matching keys in 'exports'
Object.keys(funcs).forEach(key => {
    exports[key] = funcs[key];
});

Now you can add more functions in the /functions directory and never need to edit index.ts for the added functions to be discovered and converted to Firebase cloud functions.

Firefuncs decorators

Multiple decorators

Decorators that start with on (like onFirestoreCreate, onStorageObjectArchive) are primary decorators. They are the ones that ultimately determine what type of cloud function is created from a decorated TypeScript class method.

You can apply multiple primary decorators on a single class method. You can even repeat a primary decorator multiple times on a single class method. This has the effect of creating multiple cloud functions from a single class method, one cloud function for each primary decorator.

Autogenerated cloud function names

Specifying name in func

You can specify a name for the produced cloud function by supplying a name argument to the @func decorator.

import { func, onHttpsRequest } from 'firefuncs';

export class Hello {
    @func('my_cloud_function')
    @onHttpsRequest()
    public helloWorld(request, response) {
        response.send('Hello from Firebase!\n\n');
    }
}

The produced cloud function will be named my_cloud_function.

Specifying no name in func

If you supply no name argument to the @func decorator, the produced cloud function will be named using the name of the TypeScript class and the name of the method, concatenated using an underscore (_).

import { func, onHttpsRequest } from 'firefuncs';

export class Hello {
    @func()
    @onHttpsRequest()
    public helloWorld(request, response) {
        response.send('Hello from Firebase!\n\n');
    }
}

The produced cloud function will be named Hello_helloWorld.

Applying multiple primary decorators on a method

If multiple primary decorators are applied to a method, the produced cloud functions will be named as described above, followed by a number (ranging from 1 to n, where n is the number of primary decorators applied to the method), followed by an underscore (_), and followed by the name of the decorator.

Example 1

import { func, onStorageObjectArchive, onStorageObjectDelete, onStorageObjectFinalize } from 'firefuncs';

export class Hello {
    @func('my_cloud_function')
    @onStorageObjectArchive()
    @onStorageObjectArchive()
    @onStorageObjectDelete()
    @onStorageObjectFinalize()
    public helloWorld(object) {
        response.send('Hello from Firebase!\n\n');
    }
}

This will produce 4 cloud functions named

  • my_cloud_function1_onStorageObjectFinalize
  • my_cloud_function2_onStorageObjectDelete
  • my_cloud_function3_onStorageObjectArchive
  • my_cloud_function4_onStorageObjectArchive

Example 2

import { func, onStorageObjectArchive, onStorageObjectDelete, onStorageObjectFinalize } from 'firefuncs';

export class Hello {
    @func()
    @onStorageObjectArchive()
    @onStorageObjectArchive()
    @onStorageObjectDelete()
    @onStorageObjectFinalize()
    public helloWorld(object) {
        response.send('Hello from Firebase!\n\n');
    }
}

This will produce 4 cloud functions named

  • Hello_helloWorld1_onStorageObjectFinalize
  • Hello_helloWorld2_onStorageObjectDelete
  • Hello_helloWorld3_onStorageObjectArchive
  • Hello_helloWorld4_onStorageObjectArchive