Aș dori pentru a crea Cloud multiple Funcții pentru Firebase și implementați-le pe toate în același timp la un proiect. Am dori, de asemenea, pentru a separa fiecare funcție într-un fișier separat. În prezent, pot crea mai multe funcții, dacă le-am pus amândoi în index.js cum ar fi:
exports.foo = functions.database.ref('/foo').onWrite(event => {
...
});
exports.bar = functions.database.ref('/bar').onWrite(event => {
...
});
Cu toate acestea, aș dori să pun foo bar și în fișiere separate. Am incercat asa:
/functions
|--index.js (blank)
|--foo.js
|--bar.js
|--package.json
în cazul în care foo.js este
exports.foo = functions.database.ref('/foo').onWrite(event => {
...
});
și bar.js este
exports.bar = functions.database.ref('/bar').onWrite(event => {
...
});
Există o modalitate de a realiza acest lucru fără a pune toate funcțiile în index.js?
Ah, Cloud Funcții pentru Firebase sarcina nod module, în mod normal, astfel încât aceasta funcționează
structura:
/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) => {
...
};
Răspunsul de @jasonsirota a fost de foarte mare ajutor. Dar poate fi util pentru a vedea mai detaliată cod, mai ales în cazul HTTP declanșat funcții.
Folosind aceeași structură ca în @jasonsirota's a răspunde, să spunem că doriți să aveți două HTTP funcții de declanșare în două fișiere diferite:
structura de directoare:
/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');
}
Update: Acest doc ar trebui ajuta, răspunsul meu este mai vechi decât acest doc.
Aici este modul în care eu personal făcut-o cu mașina de scris:
/functions
|--src
|--index.ts
|--http-functions.ts
|--main.js
|--db.ts
|--package.json
|--tsconfig.json
Permiteți-mi să încep prin a-ți dau două avertismente pentru a face acest lucru:
Pentru punctul 2 am'm nu sunt sigur de ce. Secundo ar trebui să-mi respecte configurația index, principal și db exact (cel puțin să-l încercați).
index.ts : se ocupa cu exportul. Găsesc că este mai curat pentru a lăsa index.ts ocupă cu exporturile.
// main must be before functions
export * from './main';
export * from "./http-functions";
principal.ts: Oferte cu inițializare.
import { config } from 'firebase-functions';
import { initializeApp } from 'firebase-admin';
initializeApp(config().firebase);
export * from "firebase-functions";
db.ts: doar reexporting db deci numele său este mai scurt decât date()`
import { database } from "firebase-admin";
export const db = database();
http-funcții.ts
// db 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);
}
Cu Nodul 8 ESTE acum disponibil cu Nor/Firebase Funcții puteți face următoarele cu răspândirea operatori:
"engines": {
"node": "8"
},
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
};
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);
});
În cazul în care cu Babel/Curge ar arata astfel:
.
├── /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
- export Principal(s)export * from './someFuncA.js';
export * from './someFuncB.js';
src/db.js
- Cloud SQL Client pentru Postgresimport { 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 Clientimport firebase from 'firebase-admin';
import { config } from 'firebase-functions';
firebase.initializeApp(config().firebase);
export default firebase.firestore();
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);
});
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/**"
]
}
}
{
"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
Pentru a fi păstrat simplu (dar functioneaza), eu personal am structurat un astfel de cod.
Aspect
├── /src/
│ ├── index.ts
│ ├── foo.ts
│ ├── bar.ts
| ├── db.ts
└── package.json
foo.ts
import * as functions from 'firebase-functions';
export const fooFunction = functions.database()......... {
//do your function.
}
export const someOtherFunction = functions.database().......... {
// do the thing.
}
bar.ts
import * as functions from 'firebase-functions';
export const barFunction = functions.database()......... {
//do your function.
}
export const anotherFunction = functions.database().......... {
// do the thing.
}
db.ts
import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';
export const firestore = admin.firestore();
export const realtimeDb = admin.database();
index.ts
import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';
admin.initializeApp(functions.config().firebase);
// above codes only needed if you use firebase admin
export * from './foo';
export * from './bar';
Lucrări pentru directoarele de orice niveluri imbricate. Doar urmați modelul în interiorul directoare de asemenea.
credit a @zaidfazil răspunde
Pentru a fi păstrat simplu (dar functioneaza), eu personal am structurat un astfel de cod.
Aspect
├── /src/
│ ├── index.ts
│ ├── foo.ts
│ ├── bar.ts
└── package.json
foo.ts
export const fooFunction = functions.database()......... {
//do your function.
}
export const someOtherFunction = functions.database().......... {
// do the thing.
}
bar.ts
export const barFunction = functions.database()......... {
//do your function.
}
export const anotherFunction = functions.database().......... {
// do the thing.
}
index.ts
import * as fooFunctions from './foo';
import * as barFunctions from './bar';
module.exports = {
...fooFunctions,
...barFunctions,
};
Lucrări pentru directoarele de orice niveluri imbricate. Doar urmați modelul în interiorul directoare de asemenea.
Acest format permite puncte de intrare pentru a găsi funcția suplimentare de fișiere, și de export fiecare funcție în cadrul fiecărui fișier, în mod automat.
Principalul Punct De Intrare Script
Găsește toate .js fișiere în interiorul funcțiilor dosar, iar exporturile fiecare funcție exportate din fiecare fișier.
const fs = require('fs');
const path = require('path');
// Folder where all your individual Cloud Functions files are located.
const FUNCTIONS_FOLDER = './scFunctions';
fs.readdirSync(path.resolve(__dirname, FUNCTIONS_FOLDER)).forEach(file => { // list files in the folder.
if(file.endsWith('.js')) {
const fileBaseName = file.slice(0, -3); // Remove the '.js' extension
const thisFunction = require(`${FUNCTIONS_FOLDER}/${fileBaseName}`);
for(var i in thisFunction) {
exports[i] = thisFunction[i];
}
}
});
Exemplu de Export de Multe Funcții dintr-Un Fișier
const functions = require('firebase-functions');
const query = functions.https.onRequest((req, res) => {
let query = req.query.q;
res.send({
"You Searched For": query
});
});
const searchTest = functions.https.onRequest((req, res) => {
res.send({
"searchTest": "Hi There!"
});
});
module.exports = {
query,
searchTest
}
http accesibile finale sunt numit în mod corespunzător
✔ functions: query: http://localhost:5001/PROJECT-NAME/us-central1/query
✔ functions: helloWorlds: http://localhost:5001/PROJECT-NAME/us-central1/helloWorlds
✔ functions: searchTest: http://localhost:5001/PROJECT-NAME/us-central1/searchTest
Un dosar
Dacă aveți doar câteva fișiere suplimentare (de exemplu, doar unul), puteți folosi:
const your_functions = require('./path_to_your_functions');
for (var i in your_functions) {
exports[i] = your_functions[i];
}
bigcodenerd.org contur's un simplu arhitectura model în scopul de a avea metode separate în diferite fișiere și exportate în o linie în index.js fișier.
Arhitectura pentru proiect în acest eșantion este următoarea:
projectDirectory
index.js
const admin = require('firebase-admin');
const podcast = require('./podcast');
const profile = require('./profile');
admin.initializeApp();
exports.getPodcast = podcast.getPodcast();
exports.removeProfile = profile.removeProfile();
podcast.js
const functions = require('firebase-functions');
exports.getPodcast = () => functions.https.onCall(async (data, context) => {
...
return { ... }
});
Același model ar putea fi utilizate pentru removeProfile
metoda în profile fișier.
Există o destul de bună modalitate de a organiza toate dvs. de cloud funcțiile pe termen lung. Am făcut asta recent și este de lucru impecabil.
Ceea ce am făcut a fost să organizeze fiecare nor funcție în foldere separate pe baza lor de a declanșa efectul. Fiecare nor funcția de nume se termină cu *.f.js
. De exemplu, dacă ați avut onCreate " și "onUpdatedeclanseaza pe utilizator/{id}/document/{documentId}
apoi, creați două fișiere onCreate.f.js" și "onUpdate.f.jsin directorul
funcții/utilizator/document/și funcția dumneavoastră va fi numit
userDocumentOnCreate" și " userDocumentOnUpdate` respectiv. (1)
Aici este un eșantion directorul avem:
functions/
|----package.json
|----index.js
/----user/
|-------onCreate.f.js
|-------onWrite.f.js
/-------document/
|------------onCreate.f.js
|------------onUpdate.f.js
/----books/
|-------onCreate.f.js
|-------onUpdate.f.js
|-------onDelete.f.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const db = admin.database();
const documentsOnCreate = functions.database
.ref('user/{userId}/document/{documentId}')
.onCreate((snap, context) => {
// your code goes here
});
exports = module.exports = documentsOnCreate;
const glob = require("glob");
const camelCase = require('camelcase');
const admin = require('firebase-admin');
const serviceAccount = require('./path/to/ServiceAccountKey.json');
try {
admin.initializeApp({ credential: admin.credential.cert(serviceAccount),
databaseURL: "Your database URL" });
} catch (e) {
console.log(e);
}
const files = glob.sync('./**/*.f.js', { cwd: __dirname });
for (let f = 0, fl = files.length; f < fl; f++) {
const file = files[f];
const functionName = camelCase(file.slice(0, -5).split('/'));
if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === functionName) {
exports[functionName] = require(file);
}
}
(1): puteți folosi orice nume doriți. Pentru mine, onCreate.f.js, onUpdate.f.js etc. par mai relevante pentru tipul de declanșare sunt.
Deci am acest proiect, care are funcții de fundal și http funcții. Am, de asemenea, teste pentru unitate de testare. CI/CD va face viața mult mai ușoară atunci când implementarea cloud funcții
|-- package.json
|-- cloudbuild.yaml
|-- functions
|-- index.js
|-- background
| |-- onCreate
| |-- index.js
|-- create.js
|
|-- http
| |-- stripe
| |-- index.js
| |-- payment.js
|-- utils
|-- firebaseHelpers.js
|-- test
|-- ...
|-- package.json
Notă: `utils/ dosarul este pentru cota de cod între funcții
Aici puteți importa doar toate funcțiile de care aveți nevoie și să le declare. Nu trebuie sa ai logica aici. Ea face curat în opinia mea. `javascript necesită('modulul-alias/register'); const funcții = necesită('firebase-funcții');
const onCreate = necesită('@fundal/onCreate'); const onDelete = necesită('@fundal/onDelete'); const onUpdate = necesită('@fundal/onUpdate');
const tururi = necesită('@http/tours'); const dungă = necesită('@http/stripe');
const docPath = 'excursii/{tourId}';
module.exporturile.onCreate = funcții.firestore.document(docPath).onCreate(onCreate); module.exporturile.onDelete = funcții.firestore.document(docPath).onDelete(onDelete); module.exporturile.onUpdate = funcții.firestore.document(docPath).onUpdate(onUpdate);
module.exporturile.excursii = funcții.https.onRequest(excursii); module.exporturile.dungă = funcții.https.onRequest(bandă); ``
Cum despre a avea continuu de integrare și implementare de fiecare dată când apăsați modificările la repo? Puteți să-l avea, cu ajutorul google google cloud construi. L's gratuit până la un punct :) Verifica acest lucru link.
./cloudbuild.yaml ``yaml pașii de mai jos:
substituții: _FIREBASE_TOKEN: nimic ``
Eu folosesc un vanilla JS bootloader pentru a auto-includ toate funcțiile pe care vreau să o utilizați.
├── /functions
│ ├── /test/
│ │ ├── testA.js
│ │ └── testB.js
│ ├── index.js
│ └── package.json
index.js (bootloader)
/**
* The bootloader reads all directories (single level, NOT recursively)
* to include all known functions.
*/
const functions = require('firebase-functions');
const fs = require('fs')
const path = require('path')
fs.readdirSync(process.cwd()).forEach(location => {
if (!location.startsWith('.')) {
location = path.resolve(location)
if (fs.statSync(location).isDirectory() && path.dirname(location).toLowerCase() !== 'node_modules') {
fs.readdirSync(location).forEach(filepath => {
filepath = path.join(location, filepath)
if (fs.statSync(filepath).isFile() && path.extname(filepath).toLowerCase() === '.js') {
Object.assign(exports, require(filepath))
}
})
}
}
})
Acest exemplu index.js fișier de auto-include directoare în rădăcină. Acesta ar putea fi extins pentru a mers pe jos directoare, onoare .gitignore, etc. Acest lucru a fost suficient pentru mine.
Cu indicele de fișier în loc, adăugarea de noi funcții este banal.
/test/testA.js
const functions = require('firebase-functions');
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!");
});
/test/testB.js
const functions = require('firebase-functions');
exports.helloWorld2 = functions.https.onRequest((request, response) => {
response.send("Hello again, from Firebase!");
});
`npm rula servi randamente:
λ ~/Workspace/Ventures/Author.io/Firebase/functions/ npm run serve
> functions@ serve /Users/cbutler/Workspace/Ventures/Author.io/Firebase/functions
> firebase serve --only functions
=== Serving from '/Users/cbutler/Workspace/Ventures/Author.io/Firebase'...
i functions: Preparing to emulate functions.
Warning: You're using Node.js v9.3.0 but Google Cloud Functions only supports v6.11.5.
✔ functions: helloWorld: http://localhost:5000/authorio-ecorventures/us-central1/helloWorld
✔ functions: helloWorld2: http://localhost:5000/authorio-ecorventures/us-central1/helloWorld2
Acest flux de lucru este destul de mult doar "scrie și rula", fără a fi nevoie de a modifica index.js fișier de fiecare dată când o nouă funcție/fișier este adăugat/modificat/eliminat.
Am petrecut o mulțime de timp în căutarea pentru același lucru, și nu este ceea ce cred că este cel mai bun mod de a realiza (I'm, folosind [email protected]):
https://codeburst.io/organizing-your-firebase-cloud-functions-67dc17b3b0da
Nu sudoare ;)