Pub Version Gitter

Wrapper for firebase functions and firebase admin to run in Node.js based on package:firebase and package:firebase_functions_interop.

Note: This package is in active development and may contains bugs. Contribution is highly appreciated.

Usage

create project

mkdir example
cd example
firebase init functions
mkdir functions/node

example/functions/node/main.dart

import 'package:firebase_node/admin.dart';
import 'package:firebase_node/functions.dart';

void main() {
  functions['onCreateUser'] = functions.auth.user().onCreate(onCreateUser);

  functions['onDeleteUser'] = functions.auth.user().onDelete(onDeleteUser);

  functions['storageFunctions'] =
      functions.storage.bucket('my-bucket').object().onFinalize(onFinalize);

  // non-Future function
  functions['documentUpdate'] =
      functions.firestore.document('my-document').onUpdate((change, context) {
    print(context.auth.uid);
    return 0;
  });
}

final app = initializeApp();

//Future function must have literal
Future<int> onDeleteUser(UserRecord user, EventContext context) async {
  final ref = app.firestore().collection('userdata').doc(user.uid);
  await ref.delete();
  return 0; //Every function must return value so that Firebase functions know when the function end.
}

Future<int> onFinalize(ObjectMetadata metadata, EventContext context) async {
  final ref = app.firestore().collection('tracker').doc('my-bucket');
  final fieldsAndValues = [
    FieldPath('file', metadata.name),
    metadata.size,
    'file_count',
    FieldValue.increment(1),
  ];
  await ref.update(fieldsAndValues: fieldsAndValues);
  return 0;
}

Future<int> onCreateUser(UserRecord user, EventContext context) async {
  final ref = app.firestore().collection('userdata').doc(user.uid);
  final data = {
    'name': user.displayName,
    'email': user.email,
    'timestamp': FieldValue.serverTimestamp(),
  };
  await ref.set(data);
  return 0;
}

example/functions/build.yaml

targets:
  $default:
    builders:
      firebase_node|nodejs_builder:
        enabled: true
        options:
          # node_modules is optional to require any node modules
          node_modules:
            # This wil output
            # 'const someModule = require("module-name")'
            # 'self.someModule = someModule'
            # So if you have custom js interop you can use node module @JS('someModule')
            someModule: module-name
          dart2js_args:
            - -O1

example/functions/pubspec.yaml

name: firebase_node_example

environment:
  sdk: '>=2.8.1 <3.0.0'

dependencies:
  firebase_node:

dev_dependencies:
  build_runner:

example/functions/package.json

{
  "name": "firebase_node_example",
  "engines": {
    "node": "10"
  },
  "main": "build/node/main.dart.node.js",
  "dependencies": {
    "firebase-admin": "^8.10.0",
    "firebase-functions": "^3.6.1"
  }
}

example/firebase.json

{
  "functions": {
    "ignore": ["node_modules", ".dart_tool", "packages"]
  }
}

compile

cd functions
pub run build_runner build --output build
firebase deploy

Project Structure

example/
├─firebase.json
└─functions/
  ├─lib/
  ├─node/
  │ └─main.dart
  ├─package.json
  ├─build.yaml
  └─pubspec.yaml

Progress

firebase_node.admin

  • x app
  • x auth
  • x credential
  • x database
  • x firestore
  • x instance id
  • x machine learning
  • x messaging
  • x project management
  • x remote config
  • x security rules
  • storage (partial complete)

firebase_node.functions

  • x analytics
  • x auth
  • x crashlytics
  • x database
  • x firestore
  • x https
  • x pubsub
  • x remote config
  • x storage
  • x test lab

Features and bugs

Please file feature requests and bugs at the issue tracker.

Libraries

builder
firebase_node.admin
firebase_node.functions