Как мне организовать облачные функции для военнослужащих, чтобы развернуть несколько функций из нескольких файлов?

Я хотел бы создать несколько облачных функций для военнослужащих и развернуть их все одновременно из одного проекта. Я также хотел бы отдельно каждую функцию в отдельный файл. В настоящее время я могу создать несколько функций, если я положила их в 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?

Комментарии к вопросу (3)
Решение

Ах, облачные функции для загрузки опорного пункта обычно узел модулей, так что это работает

структура:

/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) => {
    ...
};
Комментарии (5)

Ответ по @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'); 
}
Комментарии (1)

Обновление: этот документ должен помочь, мой ответ-старше этого документа.


Вот как я лично это сделал с TypeScript:

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

Позвольте мне предварить это, давая два предупреждения, чтобы сделать эту работу:

  1. порядок ввоза / вопросам экспорта в индекс.ТС
  2. БД должна быть в отдельном файле

За пункт номер 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);
}
Комментарии (5)

С узла 8 ЛТС теперь доступен с облака/функции опорного пункта, вы можете сделать следующее с распространением операторов:

пакет### /.в 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);
  });
Комментарии (5)

В случае с Бабель/поток это будет выглядеть так:

Макет Каталога

.
├── /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 для Postgres

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

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

<БР />

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
Комментарии (0)

Чтобы быть простой (но работает), лично я структурированных мой код вроде этого.

*План ***

├── /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 ответить

Комментарии (3)

Чтобы быть простой (но работает), лично я структурированных мой код вроде этого.

*План ***

├── /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,
};

Работает для каталогов любых уровней вложенности. Просто следуйте схеме в каталогах тоже.

Комментарии (6)

Этот формат позволяет вашей точки входа, чтобы найти дополнительные файлы функции, а также экспортировать каждую функцию в каждом файле, автоматически.

Основная Точка Входа Скрипта

Находит все .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];
}

в

Комментарии (1)

bigcodenerd.org плана'ы простой шаблон архитектура для того, чтобы иметь методы разделяются на различные файлы и экспортировать в одной строкой в index.файл js.

Архитектура проекта в этом примере следующие:

projectDirectory

  • index.js
  • podcast.js
  • profile.js

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.

Комментарии (0)

Есть очень хороший способ, чтобы организовать все ваши облачные функции на длительный срок. Я сделал это недавно, и она работает безупречно.

Что я сделал, организовать для каждой функции облака в отдельные папки по их вызвать конечную точку. Каждая функция облако именем заканчивается *.Ф.Яш. Например, если у вас метод и 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;

Index.js

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 и т. д. кажется, более соответствующими виду вызвать их.

Комментарии (4)

Так у меня есть этот проект, который имеет фоновый функции и функции для 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 шаги:

  • название: "и ГКЛ.Ио/облако-строителей/НПМ"и аргументы: [на"работать" В, С "установка:функции" и]
  • название: "и ГКЛ.Ио/облако-строителей/НПМ"и аргументы: [на"тест" и]
  • название: "и ГКЛ.Ио/${PROJECT_ID}/военнослужащих"и аргументы: [ на "развернуть" и, на " - только" Ну, на "функции" и, " С-Р" и, я ему: "${PROJECT_ID}&;, на "--Знак" и, я ему: "${_FIREBASE_TOKEN}&; ]

замены: _FIREBASE_TOKEN: ничего ``

Комментарии (2)

Я использую ваниль загрузчик 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 файл каждый раз, когда новая функция/файл добавлен/изменен/удален.

Комментарии (1)

Я провел много времени в поисках той же, и есть то, что я думаю, что это лучший способ этого добиться (Я'м через firebase@7.3.0):

https://codeburst.io/organizing-your-firebase-cloud-functions-67dc17b3b0da

Не парься ;)

Комментарии (0)

Здесь'ы простой ответ, если вы'вновь создавая облачные функции с TypeScript.

/functions
|--index.ts
|--foo.ts

У все ваши регулярные импорта в верхней просто экспортировать все функции с именем foo.ТС`.

экспорт * с './фу';`

Комментарии (0)