Skip to content

IO-Design-Team/firebase_js_interop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

83 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Wrappers and tools for composing Firebase Cloud Functions in the Dart language

Features

Legend

πŸŸ₯ No interop
🟧 Limited interop
🟨 Partial interop
🟩 Full interop

Admin

Service Status Comment
App 🟩
App Check πŸŸ₯ App Check enforcement for callable functions is supported
Auth πŸŸ₯
Credential πŸŸ₯
Database πŸŸ₯
Eventarc πŸŸ₯
Extensions πŸŸ₯
Firestore 🟩
Functions πŸŸ₯
Installations πŸŸ₯
Messaging 🟧 Only message sending
Project Management πŸŸ₯
Remote Config πŸŸ₯
Security Rules πŸŸ₯
Storage πŸŸ₯

Functions

Service Status
Alerts πŸŸ₯
Database πŸŸ₯
Eventarc πŸŸ₯
Firestore 🟩
HTTPS 🟩
Identity 🟩
PubSub πŸŸ₯
Remote Config πŸŸ₯
Scheduler πŸŸ₯
Storage πŸŸ₯
Tasks πŸŸ₯
Test Lab πŸŸ₯
Global Options πŸŸ₯
onInit πŸŸ₯

Future

Interop with the following packages is planned, but not yet implemented:

Getting started

Install the firebase tools

Usage

Project structure

Create the following dart/flutter packages:

Package Purpose
{app} Flutter app
{app}_core Base core package
{app}_core_flutter Core package for Flutter app
{app}_core_js_interop Core package for Cloud Functions
{app}_firebase/functions Firebase Cloud Functions

The purpose of the three core packages is as follows:

  • Flutter apps (besides the web platform) cannot import js_interop code
  • Transpiled dart2js code cannot transitively depend on Flutter

This means the base {app}_core package cannot depend on anything that depends on Flutter. Those dependencies should be used in {app}_core_flutter instead.

Create the Firebase project

Run firebase init in {app}_firebase. Choose javascript as the language for Cloud Functions.

Set up FCF for Dart

Make the following modifications to files in {app}_firebase:

firebase.json

Add the following ignores

{
  "functions": [
    {
      "ignore": [
        "pubspec.*",
        "src",
        "tool",
        "analysis_options.yaml",
        ".dart_tool"
      ]
    }
  ]
}

functions/.gitignore

# Compiled JavaScript files
lib/**

# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/

functions/package.json

{
  "scripts": {
    "lint": "dart analyze --fatal-infos",
    "build": "dart run tool/build.dart"
  },
  "main": "lib/index.js"
}

functions/pubspec.yaml

dependencies:
  {app}_core_js_interop:
    path: ../../{app}_core_js_interop
  firebase_js_interop: latest

functions/src/index.dart

This is where the Dart Cloud Functions code lives. See below for an example.

functions/tool/build.dart

This is what compiles index.dart into an index.js file that can run on Cloud Functions

import 'package:firebase_js_interop/build.dart';

void main() async {
  await buildCloudFunctions();
}

Writing models

Create the base models in {app}_core, then augment them with json serialization in {app}_core_flutter and {app}_core_js_interop. See the example project for more details on how to use json serialization with both firebase_js_interop and cloud_firestore_odm.

Writing Cloud Functions

Writing Cloud Functions in Dart is very similar to writing them in TypeScript:

import 'dart:js_interop';
import 'dart:js_interop_unsafe';

import 'package:firebase_js_interop/functions.dart';
import 'package:firebase_js_interop/node.dart';
import 'package:firebase_js_interop/express.dart' as express;

void main() {
  exports['helloWorld'] = FirebaseFunctions.https.onRequest(
    (Request request, express.Response response) {
      return response.send('Hello from Firebase!'.toJS);
    }.toJS,
  );
}

Make sure to return promises for async operations:

import 'dart:js_interop';
import 'dart:js_interop_unsafe';

import 'package:firebase_js_interop/functions.dart';
import 'package:firebase_js_interop/js.dart';
import 'package:firebase_js_interop/node.dart';
import 'package:firebase_js_interop/admin.dart';

void main() {
  exports['onMessageCreated'] = FirebaseFunctions.firestore.onDocumentCreated(
    '/chats/{chatId}/messages/{messageId}'.toJS,
    (FirestoreEvent<DocumentSnapshot> event) {
      return promise(() async {
        await Future.delayed(const Duration(seconds: 1));
      });
    }.toJS,
  );
}

Deploying Cloud Functions

  1. dart run tool/build.dart
  2. firebase deploy --only functions

The compiled JS will also work in the Firebase emulators

Additional information

See firebase_rules for writing Firebase security rules in Dart.

Contributing

There are many unimplemented features. Please feel free to contribute if any necessary components are missing.

See CONTRIBUTING.md for details