201 votes

Comment structurer Cloud Functions pour Firebase afin de déployer plusieurs fonctions à partir de plusieurs fichiers?

Je voudrais créer plusieurs Cloud Fonctions de Firebase et de les déployer en même temps d'un projet. Je tiens également à séparer chaque fonction dans un fichier séparé. Actuellement je peux créer plusieurs fonctions si je les ai mis à la fois dans index.js tels que:

exports.foo = functions.database.ref('/foo').onWrite(event => {
    ...
});

exports.bar = functions.database.ref('/bar').onWrite(event => {
    ...
});

Cependant, je voudrais mettre foo et bar dans des fichiers séparés. J'ai essayé ceci:

/functions
|--index.js (blank)
|--foo.js
|--bar.js
|--package.json

où foo.js est

exports.foo = functions.database.ref('/foo').onWrite(event => {
    ...
});

et bar.js est

exports.bar = functions.database.ref('/bar').onWrite(event => {
    ...
});

Est-il un moyen pour y parvenir sans mettre toutes les fonctions de index.js?

142voto

jasonsirota Points 1619

Ah, les fonctions de nuage pour les modules de nœud de chargement Firebase normalement, donc cela fonctionne

structure:

 /functions
|--index.js
|--foo.js
|--bar.js
|--package.json
 

index.js:

 const functions = require('firebase-functions');
const fooModule = require('./foo');
const barModule = require('./bar');

exports.foo = functions.database.ref('/foo').onWrite(fooModule.handler);
exports.bar = functions.database.ref('/bar').onWrite(barModule.handler);
 

foo.js:

 exports.handler = (event) => {
    ...
};
 

bar.js:

 exports.handler = (event) => {
    ...
};
 

90voto

College Student Points 727

La réponse de @jasonsirota a été très utile. Mais il peut être utile de voir un code plus détaillé, en particulier dans le cas de fonctions déclenchées par HTTP.

En utilisant la même structure que dans la réponse de @ jasonsirota, disons que vous souhaitez avoir deux fonctions de déclencheur HTTP distinctes dans deux fichiers différents:

structure de répertoire:

     /functions
       |--index.js
       |--foo.js
       |--bar.js
       |--package.json`
 

index.js:

 'use strict';
const fooFunction = require('./foo');
const barFunction = require('./bar');

// Note do below initialization tasks in index.js and
// NOT in child functions:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase); 
const database = admin.database();

// Pass database to child functions so they have access to it
exports.fooFunction = functions.https.onRequest((req, res) => {
    fooFunction.handler(req, res, database);
});
exports.barFunction = functions.https.onRequest((req, res) => {
    barFunction.handler(req, res, database);
});
 

foo.js:

  exports.handler = function(req, res, database) {
      // Use database to declare databaseRefs:
      usersRef = database.ref('users');
          ...
      res.send('foo ran successfully'); 
   }
 

bar.js:

 exports.handler = function(req, res, database) {
  // Use database to declare databaseRefs:
  usersRef = database.ref('users');
      ...
  res.send('bar ran successfully'); 
}
 

59voto

Ced Points 6385

Voici comment j'ai personnellement fait avec la machine:

/functions
   |--src
      |--index.ts
      |--http-functions.ts
      |--main.js
      |--db.ts
   |--package.json
   |--tsconfig.json

Permettez-moi de commencer en donnant deux avertissements pour faire ce travail:

  1. l'ordre de l'importation / l'exportation questions de l'index.ts
  2. la db doit être un fichier séparé

Pour le point numéro 2, je ne sais pas pourquoi. Secundo, vous devriez respecter ma configuration de l'index, une principale et une db exactement (au moins essayer).

index.ts : traite de l'exportation. Je trouve ça plus propre à laisser l'index.ts traiter les exportations.

// main must be before functions
export * from './main';
export * from "./http-functions";

principal.ts: Traite de l'initialisation.

import { config } from 'firebase-functions';
import { initializeApp } from 'firebase-admin';

initializeApp(config().firebase);
export * from "firebase-functions";

db.ts: il suffit de ré-exportation de la db de sorte que son nom est plus court que database()

import { database } from "firebase-admin";

export const db = database();

http-fonctions.ts

// de must be imported like this
import { db } from './db';
// you can now import everything from index. 
import { https } from './index';  
// or (both work)
// import { https } from 'firebase-functions';

export let newComment = https.onRequest(createComment);

export async function createComment(req: any, res: any){
    db.ref('comments').push(req.body.comment);
    res.send(req.body.comment);
}

28voto

Luke Pighetti Points 612

Avec Node 8 LTS maintenant disponible avec les fonctions Cloud / Firebase, vous pouvez effectuer les opérations suivantes avec des opérateurs étendus:

/package.json

 "engines": {
  "node": "8"
},
 

/index.js

 const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();

module.exports = {
  ...require("./lib/foo.js"),
  // ...require("./lib/bar.js") // add as many as you like
};
 

/lib/foo.js

 const functions = require("firebase-functions");
const admin = require("firebase-admin");

exports.fooHandler = functions.database
  .ref("/food/{id}")
  .onCreate((snap, context) => {
    let id = context.params["id"];

    return admin
      .database()
      .ref(`/bar/${id}`)
      .set(true);
  });
 

13voto

Konstantin Tarkus Points 16862

Dans le cas avec Babel/Flux il devrait ressembler à ceci:

Annuaire De Mise En Page

.
├── /build/                     # Compiled output for Node.js 6.x
├── /src/                       # Application source files
│   ├── db.js                   # Cloud SQL client for Postgres
│   ├── index.js                # Main export(s)
│   ├── someFuncA.js            # Function A
│   ├── someFuncA.test.js       # Function A unit tests
│   ├── someFuncB.js            # Function B
│   ├── someFuncB.test.js       # Function B unit tests
│   └── store.js                # Firebase Firestore client
├── .babelrc                    # Babel configuration
├── firebase.json               # Firebase configuration
└── package.json                # List of project dependencies and NPM scripts


src/index.js - Principal produit d'exportation(s)

export * from './someFuncA.js';
export * from './someFuncB.js';


src/db.js - Cloud SQL Client pour Postgres

import { Pool } from 'pg';
import { config } from 'firebase-functions';

export default new Pool({
  max: 1,
  user: '<username>',
  database: '<database>',
  password: config().db.password,
  host: `/cloudsql/${process.env.GCP_PROJECT}:<region>:<instance>`,
});


src/store.js - Firebase Firestore Client

import firebase from 'firebase-admin';
import { config } from 'firebase-functions';

firebase.initializeApp(config().firebase);

export default firebase.firestore();


src/someFuncA.js - Fonction D'Une

import { https } from 'firebase-functions';
import db from './db';

export const someFuncA = https.onRequest(async (req, res) => {
  const { rows: regions } = await db.query(`
    SELECT * FROM regions WHERE country_code = $1
  `, ['US']);
  res.send(regions);
});


src/someFuncB.js - Fonction B

import { https } from 'firebase-functions';
import store from './store';

export const someFuncB = https.onRequest(async (req, res) => {
  const { docs: regions } = await store
    .collection('regions')
    .where('countryCode', '==', 'US')
    .get();
  res.send(regions);
});


.babelrc

{
  "presets": [["env", { "targets": { "node": "6.11" } }]],
}


firebase.json

{
  "functions": {
    "source": ".",
    "ignore": [
      "**/node_modules/**"
    ]
  }
}


package.json

{
  "name": "functions",
  "verson": "0.0.0",
  "private": true,
  "main": "build/index.js",
  "dependencies": {
    "firebase-admin": "^5.9.0",
    "firebase-functions": "^0.8.1",
    "pg": "^7.4.1"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.0",
    "babel-jest": "^22.2.2",
    "babel-preset-env": "^1.6.1",
    "jest": "^22.2.2"
  },
  "scripts": {
    "test": "jest --env=node",
    "predeploy": "rm -rf ./build && babel --out-dir ./build src",
    "deploy": "firebase deploy --only functions"
  }
}


$ yarn install                  # Install project dependencies
$ yarn test                     # Run unit tests
$ yarn deploy                   # Deploy to Firebase

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X