Я хотел бы создать несколько облачных функций для военнослужащих и развернуть их все одновременно из одного проекта. Я также хотел бы отдельно каждую функцию в отдельный файл. В настоящее время я могу создать несколько функций, если я положила их в index.js такие как:
exports.foo = functions.database.ref('/foo').onWrite(event => {
...
});
exports.bar = functions.database.ref('/bar').onWrite(event => {
...
});
Однако я хотел бы foo и Bar в отдельных файлах. Я попытался это:
/functions
|--index.js (blank)
|--foo.js
|--bar.js
|--package.json
где foo.js это
exports.foo = functions.database.ref('/foo').onWrite(event => {
...
});
и bar.js это
exports.bar = functions.database.ref('/bar').onWrite(event => {
...
});
Есть ли способ достичь этого без применения всех функций в index.js?
Ах, облачные функции для загрузки опорного пункта обычно узел модулей, так что это работает
структура:
/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) => {
...
};
Ответ по @jasonsirota был очень полезным. Но это может быть полезно, чтобы увидеть более подробную кода, особенно в случае HTTP срабатывает функций.
Используя такую же структуру, как в @jasonsirota'ы ответьте, допустим, вы хотите иметь два отдельных триггера функции HTTP в двух разных файлах:
структура каталогов:
/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');
}
Обновление: этот документ должен помочь, мой ответ-старше этого документа.
Вот как я лично это сделал с TypeScript:
/functions
|--src
|--index.ts
|--http-functions.ts
|--main.js
|--db.ts
|--package.json
|--tsconfig.json
Позвольте мне предварить это, давая два предупреждения, чтобы сделать эту работу:
За пункт номер 2 я'м не уверен, почему. Секундо вы должны уважать мои настройки индекса, основной и ДБ ровно (по крайней мере, чтобы попробовать его).
индекс.ц : занимается экспортом. Я найти его чище, чтобы позволить индекса.ТС сделку с экспортом.
// main must be before functions
export * from './main';
export * from "./http-functions";
главная.ц: сделки с инициализацией.
import { config } from 'firebase-functions';
import { initializeApp } from 'firebase-admin';
initializeApp(config().firebase);
export * from "firebase-functions";
дБ.ц: просто реэкспорт дБ, поэтому его имя короче, чем база ()
import { database } from "firebase-admin";
export const db = database();
НТТР-функции.ТС
// 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);
}
С узла 8 ЛТС теперь доступен с облака/функции опорного пункта, вы можете сделать следующее с распространением операторов:
пакет### /.в JSON
"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);
});
В случае с Бабель/поток это будет выглядеть так:
.
├── /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 * from './someFuncA.js';
export * from './someFuncB.js';
<БР />
src/db.js
- облако клиента SQL для 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
- опорному пункту Firestore клиентаimport firebase from 'firebase-admin';
import { config } from 'firebase-functions';
firebase.initializeApp(config().firebase);
export default firebase.firestore();
<БР />
src/someFuncA.js
- функция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
- 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" } }]],
}
<БР />
опорного пункта.формат JSON
{
"functions": {
"source": ".",
"ignore": [
"**/node_modules/**"
]
}
}
<БР />
пакет###.формат 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
Чтобы быть простой (но работает), лично я структурированных мой код вроде этого.
*План ***
├── /src/
│ ├── index.ts
│ ├── foo.ts
│ ├── bar.ts
| ├── db.ts
└── package.json
ФОО.ТС
import * as functions from 'firebase-functions';
export const fooFunction = functions.database()......... {
//do your function.
}
export const someOtherFunction = functions.database().......... {
// do the thing.
}
бар.ТС
import * as functions from 'firebase-functions';
export const barFunction = functions.database()......... {
//do your function.
}
export const anotherFunction = functions.database().......... {
// do the thing.
}
дБ.ТС
import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';
export const firestore = admin.firestore();
export const realtimeDb = admin.database();
индекс.ТС
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';
Работает для каталогов любых уровней вложенности. Просто следуйте схеме в каталогах тоже.
кредит на @zaidfazil ответить
Чтобы быть простой (но работает), лично я структурированных мой код вроде этого.
*План ***
├── /src/
│ ├── index.ts
│ ├── foo.ts
│ ├── bar.ts
└── package.json
ФОО.ТС
export const fooFunction = functions.database()......... {
//do your function.
}
export const someOtherFunction = functions.database().......... {
// do the thing.
}
бар.ТС
export const barFunction = functions.database()......... {
//do your function.
}
export const anotherFunction = functions.database().......... {
// do the thing.
}
индекс.ТС
import * as fooFunctions from './foo';
import * as barFunctions from './bar';
module.exports = {
...fooFunctions,
...barFunctions,
};
Работает для каталогов любых уровней вложенности. Просто следуйте схеме в каталогах тоже.
Этот формат позволяет вашей точки входа, чтобы найти дополнительные файлы функции, а также экспортировать каждую функцию в каждом файле, автоматически.
Основная Точка Входа Скрипта
Находит все .JS файлы внутри папки функции и экспорта каждой функции, экспортируемой из каждого файла.
в
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];
}
}
});
в
Пример экспорта несколько функций из одного файла
в
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 доступных конечных точек соответствующим названием
в
✔ 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
в
Одним файлом
Если у вас есть только несколько дополнительных файлов (например, только один), вы можете использовать:
в
const your_functions = require('./path_to_your_functions');
for (var i in your_functions) {
exports[i] = your_functions[i];
}
в
bigcodenerd.org плана'ы простой шаблон архитектура для того, чтобы иметь методы разделяются на различные файлы и экспортировать в одной строкой в index.файл js.
Архитектура проекта в этом примере следующие:
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 { ... }
});
в
Тот же шаблон будет использоваться для removeProfile метод в файле profile.
Есть очень хороший способ, чтобы организовать все ваши облачные функции на длительный срок. Я сделал это недавно, и она работает безупречно.
Что я сделал, организовать для каждой функции облака в отдельные папки по их вызвать конечную точку. Каждая функция облако именем заканчивается *.Ф.Яш
. Например, если у вас метод
и onUpdate
триггеры Пользователи/{Имя пользователя}/документ/{код документа}
то создаете два файла onCreate.f.js и onUpdate.f.js
в каталог функции/пользователь/документ/ и ваша функция будет называться
userDocumentOnCreate " и " userDocumentOnUpdate` соответственно. (1)
Вот пример структуры каталогов:
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): Вы можете использовать любое имя вы хотите. Для меня onCreate.f.js, onUpdate.f.js и т. д. кажется, более соответствующими виду вызвать их.
Так у меня есть этот проект, который имеет фоновый функции и функции для HTTP. У меня тоже тесты для модульного тестирования. Ки/КД сделает вашу жизнь намного проще при развертывании облачных функций
|-- 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
Примечание: папку utils/
предназначен для совместного использования кода между функциями
functions/index.js ### Здесь вы можете просто импортировать все функции вам нужно, и объявлять их. Не нужно иметь логику здесь. Это делает его чище на мой взгляд. ``в JavaScript требуют('модуль-псевдоним/Регистрация'); константные функции = требуют('военнослужащих-функции');
константный метод onCreate = требуют('@фон/метод onCreate'); константный onDelete = требуют('@фон/onDelete'); константный onUpdate = требуют('@фон/onUpdate');
константный туры = требуют('@протоколу HTTP/туры'); константный полоса = требуют('@протоколу HTTP/полоса');
константный компания docpath = 'туры/{tourId}';
модуль.экспорт.метод onCreate = функции.firestore.документ(докопать).метод onCreate(метод onCreate); модуль.экспорт.onDelete = функции.firestore.документ(докопать).onDelete(onDelete); модуль.экспорт.onUpdate = функции.firestore.документ(докопать).onUpdate(onUpdate);
модуль.экспорт.туры = функции.протоколу HTTPS.по просьбе(туры); модуль.экспорт.нашивки = функции.протоколу HTTPS.по просьбе(полоса); ``
Как насчет того, непрерывной интеграции и развертывания каждый раз, когда вы толкать свои изменения в репозиторий? Вы можете взять его с помощью Google облако построить Гугл. Это's бесплатная до определенного момента :) проверить это link.
./cloudbuild.и YAML ``в YAML шаги:
замены: _FIREBASE_TOKEN: ничего ``
Я использую ваниль загрузчик JS, чтобы автоматически включать все функции, которые я хочу использовать.
├── /functions
│ ├── /test/
│ │ ├── testA.js
│ │ └── testB.js
│ ├── index.js
│ └── package.json
index.js (бутлоадера)
в
/**
* 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))
}
})
}
}
})
В этом примере index.js файл только авто-каталоги в корень. Он может быть расширен, чтобы ходить каталогах, честь .гитюдного и т. д. Это было для меня достаточно.
С индексного файла в место, добавляя новые функции тривиально.
/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!");
});
НПМ запустить служить
дает:
в
λ ~/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
Этот процесс в значительной степени просто, что "писать и запускать" и, без изменения index.js файл каждый раз, когда новая функция/файл добавлен/изменен/удален.
Я провел много времени в поисках той же, и есть то, что я думаю, что это лучший способ этого добиться (Я'м через [email protected]):
https://codeburst.io/organizing-your-firebase-cloud-functions-67dc17b3b0da
Не парься ;)
Здесь'ы простой ответ, если вы'вновь создавая облачные функции с TypeScript.
/functions
|--index.ts
|--foo.ts
У все ваши регулярные импорта в верхней просто экспортировать все функции с именем foo.ТС`.
экспорт * с './фу';`