Como estruturo o Cloud Functions for Firebase para implantar várias funções de vários arquivos?

164

Gostaria de criar várias funções de nuvem para o Firebase e implantá-las todas ao mesmo tempo em um projeto. Eu também gostaria de separar cada função em um arquivo separado. Atualmente, posso criar várias funções se colocá-las no index.js, como:

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

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

No entanto, eu gostaria de colocar foo e bar em arquivos separados. Eu tentei isso:

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

onde está foo.js

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

e bar.js é

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

Existe uma maneira de fazer isso sem colocar todas as funções no index.js?

jasonsirota
fonte
1
@JPVentura. Realmente não te entendo bem. Por favor explique.
HuyLe
Isso foi atualizado para a v1.0? Estou tendo problemas: stackoverflow.com/questions/50089807/…
tccpg288
2
FYI, este funções Firebase oficial exemplo contém vários .jsarquivos importados através de require: github.com/firebase/functions-samples/tree/master/...
xanderiel
Isso pode ser útil: stackoverflow.com/questions/43486278/…
Ramesh-X

Respostas:

126

Ah, o Cloud Functions para Firebase carrega módulos de nó normalmente, então isso funciona

estrutura:

/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
fonte
1
Por exemplo, posso ter várias funções no módulo foo? Se sim, como é melhor implementá-lo?
Alexander Khitev
1
Suponho que você possa atribuir diferentes manipuladores a diferentes funções exportadas de foo: export.bar = functions.database.ref ('/ foo'). OnWrite (fooModule.barHandler); export.baz = funções.database.ref ('/ bar'). onWrite (fooModule.bazHandler);
Jasonsirota 19/05
44
Eu não gosto dessa solução porque move as informações (ou seja, os caminhos do banco de dados) de foo.js e bar.js para index.js, o que meio que anula o ponto de ter esses arquivos separados.
bvs
Concordo com @bvs, acho que Ced tem uma boa abordagem. Eu vou modificá-lo ligeiramente exportando explicitamente cada módulo para fazer a index.ts super claro exemplo de exportação {newuser} de "./authenticationFunctions"
Alan
2
Acho que minha pergunta original era simplesmente implantar várias funções com um projeto sem colocar as funções no arquivo index.js, onde e como você passa as informações do banco de dados não estão no escopo. Se fosse eu, provavelmente criaria um módulo separado que controlava o acesso ao banco de dados e o exigia em foo.js e bar.js separadamente, mas essa é uma decisão estilística.
Jasonsirota # 3/17
75

A resposta de @jasonsirota foi muito útil. Mas pode ser útil ver um código mais detalhado, especialmente no caso de funções acionadas por HTTP.

Usando a mesma estrutura da resposta de @ jasonsirota, digamos que você queira ter duas funções de gatilho HTTP separadas em dois arquivos diferentes:

estrutura de diretórios:

    /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'); 
}
Estudante de faculdade
fonte
A estrutura atual no index.js não funcionou bem para mim. O que eu precisava fazer era primeiro importar os módulos do firebase, inicializar o aplicativo e depois importar as funções das outras pastas. Dessa maneira, meu aplicativo inicializa, autentica, seja qual for, e depois importa as funções que precisam que o aplicativo seja inicializado antecipadamente.
tonkatata
47

Atualização: este documento deve ajudar , minha resposta é mais antiga que este documento.


Aqui está como eu pessoalmente fiz isso com texto datilografado:

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

Permitam-me que anteceda isso, dando dois avisos para que isso funcione:

  1. a ordem de importação / exportação é importante em index.ts
  2. o banco de dados deve ser um arquivo separado

Para o ponto número 2, não sei por que. Secundo, você deve respeitar minha configuração de index, main e db exatamente (pelo menos para testá-lo).

index.ts : trata de exportação. Acho mais fácil deixar o index.ts lidar com as exportações.

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

main.ts : Lida com a inicialização.

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

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

db.ts : basta reexportar o db para que seu nome seja menor quedatabase()

import { database } from "firebase-admin";

export const db = database();

http-functions.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);
}
Ced
fonte
como é o seu tsconfig? como posso compilar em uma pasta dist e informar às funções do gcloud onde está o meu index.js? Você tem seu código no github? :)
bersling
@ choopage-JekBao desculpe, já faz muito tempo, eu não tenho mais o projeto. Se bem me lembro, você pode dar à firebase config um diretório (que é público por padrão). Eu posso estar errado embora desde já faz mais de um ano
Ced
Hey @ced - por que o conteúdo de não pode db.tsentrar main.ts(após a instanciação do administrador?). Ou você acabou de se separar dessa maneira por clareza / simplicidade?
dsg38
1
@ dsg38 este foi publicado há muito tempo, eu realmente não vejo por que deveria ser em um arquivo separado olhando para a resposta agora .. eu acho que foi para maior clareza
Ced
21

Com o Node 8 LTS agora disponível com as funções Cloud / Firebase, você pode fazer o seguinte com operadores espalhados:

/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);
  });
Luke Pighetti
fonte
Gostaria de saber se o número crescente de importações diminui o início a frio de cada função ou se deve haver muitos módulos totalmente separados, desenvolvidos separadamente?
Simon Fakir
2
Eu recebo um erro de separação eslint unexpected token ...dentro do index.js.
thomas
Talvez você não estiver usando Nó 8
Lucas Pighetti
@SimonFakir good question. Você encontrou algo sobre isso?
atereshkov 9/09/19
@atereshkov sim, encontrei uma maneira de carregar apenas a função solicitada, incluindo suas dependências usando "process.env.FUNCTION_NAME" semelhante à resposta abaixo. Também posso compartilhar meu repo como referência, se você estiver interessado, entre em contato comigo.
Simon Fakir
15

Para ser simples (mas funciona), eu estruturei pessoalmente meu código assim.

Layout

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

Funciona para diretórios de qualquer nível aninhado. Apenas siga o padrão dentro dos diretórios também.

crédito para @zaidfazil resposta

Reza
fonte
1
Esta é uma das respostas mais simples para o Typecript, obrigado. Como você lida com uma única instanciação do banco de dados firebase, por exemplo? admin.initializeApp(functions.config().firestore) const db = admin.firestore();Onde você coloca isso e como você se refere a ele em foo e bar?
Elprl
Ei - por que o conteúdo não pode db.tsentrar index.ts(após a instanciação do administrador?). Ou você acabou de se separar dessa maneira por clareza / simplicidade?
dsg38 4/09/19
@ dsg38 você pode misturar todos juntos, isso deixa claro
Reza
10

No caso de Babel / Flow , ficaria assim:

Layout do diretório

.
├── /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 - Principais exportações)

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


src/db.js - Cloud SQL Client para 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 - Cliente Firestore Firebase

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

firebase.initializeApp(config().firebase);

export default firebase.firestore();


src/someFuncA.js - Função A

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 - Função 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
Konstantin Tarkus
fonte
9

O esboço do bigcodenerd.org é um padrão de arquitetura mais simples para que os métodos sejam separados em arquivos diferentes e exportados em uma linha no index.js arquivo .

A arquitetura do projeto neste exemplo é a seguinte:

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 { ... }
  });

O mesmo padrão seria usado para o removeProfilemétodo no arquivo de perfil .

Adam Hurwitz
fonte
7

Para ser simples (mas funciona), eu estruturei pessoalmente meu código assim.

Layout

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

Funciona para diretórios de qualquer nível aninhado. Apenas siga o padrão dentro dos diretórios também.

zaidfazil
fonte
Não vejo como isso poderia funcionar, pois o Firebase suporta o Nó 6.11 atualmente, que não suporta as diretivas de importação ES6?
Aodh
Se você estiver usando texto datilografado, o problema nunca deve surgir. Ultimamente, portava a maior parte do meu código para texto datilografado.
Zaidfazil
2
zaidfazil, você provavelmente deve anotar quaisquer pré-requisitos em sua resposta. @ Ah, funciona se você usar Babel da mesma maneira que Konstantin delineou em uma resposta. stackoverflow.com/questions/43486278/…
PostureOfLearning
1
obrigado. isso funcionou com texto datilografado e nó 6 :)
Ahmad Moussa
4
Em vez de importar e reexportar com operadores espalhados, você não poderia apenas ter export * from './fooFunctions';e export * from './barFunctions';no index.ts?
whatsthatitspat
5

Esse formato permite que seu ponto de entrada encontre arquivos de funções adicionais e exporte cada função dentro de cada arquivo automaticamente.

Script do ponto de entrada principal

Localiza todos os arquivos .js dentro da pasta de funções e exporta cada função exportada de cada arquivo.

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];
    }
  }
});

Exemplo de exportação de várias funções de um arquivo

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
}

pontos de extremidade acessíveis http são nomeados apropriadamente

✔ 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

Um arquivo

Se você tiver apenas alguns arquivos adicionais (por exemplo, apenas um), poderá usar:

const your_functions = require('./path_to_your_functions');

for (var i in your_functions) {
  exports[i] = your_functions[i];
}

Matthew Rideout
fonte
Isso não terá sobrecarga na inicialização para todas as instâncias de função que surgirem?
21419 Ayyappa
4

Então, eu tenho esse projeto que tem funções em segundo plano e funções http. Eu também tenho testes para testes de unidade. O CI / CD facilitará sua vida ao implantar funções na nuvem

Estrutura de pastas

|-- 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

Nota: utils/ pasta é para compartilhar código entre funções

functions / index.js

Aqui você pode apenas importar todas as funções necessárias e declará-las. Não há necessidade de lógica aqui. Isso torna mais limpo na minha opinião.

require('module-alias/register');
const functions = require('firebase-functions');

const onCreate = require('@background/onCreate');
const onDelete = require('@background/onDelete');
const onUpdate = require('@background/onUpdate');

const tours  = require('@http/tours');
const stripe = require('@http/stripe');

const docPath = 'tours/{tourId}';

module.exports.onCreate = functions.firestore.document(docPath).onCreate(onCreate);
module.exports.onDelete = functions.firestore.document(docPath).onDelete(onDelete);
module.exports.onUpdate = functions.firestore.document(docPath).onUpdate(onUpdate);

module.exports.tours  = functions.https.onRequest(tours);
module.exports.stripe = functions.https.onRequest(stripe);

CI / CD

Que tal ter integração e implantação contínuas toda vez que você envia suas alterações ao repositório? Você pode obtê-lo usando o google google cloud build . É grátis até um certo ponto :) Verifique este link .

./cloudbuild.yaml

steps:
  - name: "gcr.io/cloud-builders/npm"
    args: ["run", "install:functions"]
  - name: "gcr.io/cloud-builders/npm"
    args: ["test"]
  - name: "gcr.io/${PROJECT_ID}/firebase"
    args:
      [
        "deploy",
        "--only",
        "functions",
        "-P",
        "${PROJECT_ID}",
        "--token",
        "${_FIREBASE_TOKEN}"
      ]

substitutions:
    _FIREBASE_TOKEN: nothing
ajorquera
fonte
Eu exportei como você disse, mas a implantação do Firebase detecta a que está no final, ex: conforme seu código, é necessário apenas module.exports.stripe = functions.https.onRequest (stripe);
precisa saber é o seguinte
@ OK200 qual é o comando que você está usando com a linha de comando do firebase? Para ajudá-lo, eu vou ter de ver algum código
ajorquera
3

Existe uma maneira muito boa de organizar todas as suas funções de nuvem a longo prazo. Eu fiz isso recentemente e está funcionando perfeitamente.

O que fiz foi organizar cada função da nuvem em pastas separadas com base no ponto de extremidade do acionador. Todo nome de arquivo da função de nuvem termina com *.f.js. Por exemplo, se você tiver ativado onCreatee onUpdateacionado user/{userId}/document/{documentId}, crie dois arquivos onCreate.f.jse onUpdate.f.jsno diretório, functions/user/document/e sua função será nomeada userDocumentOnCreateeuserDocumentOnUpdate respectivamente. (1)

Aqui está uma estrutura de diretório de exemplo:

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

Função de amostra

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): Você pode usar qualquer nome que desejar. Para mim, onCreate.f.js, onUpdate.f.js etc. parecem mais relevantes para o tipo de gatilho que são.

krhitesh
fonte
1
Essa abordagem é muito legal. Eu queria saber se é possível ajustar-se para permitir barras nos nomes de função para que você possa separar diferentes versões da API, por exemplo (v1 API, API v2, etc)
Alex Sorokoletov
Por que você deseja manter versões diferentes de uma função de nuvem no mesmo projeto? Embora você possa fazer isso alterando levemente a estrutura do diretório, por padrão, index.js implementará todas as funções da nuvem, a menos que você implemente seletivamente ou use condições if em seu index.js que acabarão por sobrecarregar seu código
krhitesh
1
Eu estou bem com a implantação de tudo, eu só quero a versão das funções que eu coloco (http desencadeadas)
Alex Sorokoletov
Espero que cada gatilho http esteja em seu próprio *.f.jsarquivo. O mínimo que você pode fazer é renomear o arquivo para cada versão, acrescentando o sufixo para torná-lo algo parecido *.v1.f.jsou *.v2.f.jsetc. (Supondo que todas as suas versões de todo o seu gatilho http estejam ativas). Entre em contato se você tiver uma solução melhor.
Krhitesh
1

Eu uso um carregador de inicialização JS vanilla para incluir automaticamente todas as funções que eu quero usar.

├── /functions
   ├── /test/
      ├── testA.js
      └── testB.js
   ├── index.js
   └── package.json

index.js (carregador de inicialização)

/**
 * 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))
        }
      })
    }
  }
})

Este arquivo index.js de exemplo inclui apenas diretórios automaticamente na raiz. Poderia ser expandido para procurar diretórios, honrar .gitignore, etc. Isso foi o suficiente para mim.

Com o arquivo de índice no lugar, adicionar novas funções é trivial.

/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 run serve rendimentos:

λ ~/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

Esse fluxo de trabalho é basicamente "gravação e execução", sem a necessidade de modificar o arquivo index.js sempre que uma nova função / arquivo é adicionada / modificada / removida.

Corey
fonte
isso não será iniciado a frio?
21419 Ayyappa
1

Aqui está uma resposta simples se você estiver criando funções de nuvem com texto datilografado.

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

Perto de todas as suas importações regulares no topo, basta exportar todas as funções de foo.ts.

export * from './foo';

Markymark
fonte