Defining Cloud Functions

To tell Foundry what functions it should trigger every time you make some change to your code, you have to specify the functions field in the foundry.yaml configuration file.

After you define your Cloud Functions in the functions array, Foundry looks for a file where are all your Cloud Functions exported. There are two options for Foundry to find this file:

  1. If you have specified the main field in your package.json then Foundry takes the field's value and use it as a path to the file with all your Cloud Function exports

  2. If you have not specified the main field in your package.json then Foundry expects there is a index.js file in the same directory as your package.json with all your Cloud Function exports

Currently, Foundry supports following Firebase functions:

An example of a function inside the foundry.yaml file might look like this:

functions:
- name: myHttpsFunction
type: https
# The payload field can either be a JSON string
payload: {"field":"value"}
# or you can reference a document from your production Firestore
payload:
doc:
getFromProd:
collection: path/to/collection
id: doc-id
# or you can reference a document from the emulated Firestore
payload:
doc:
collection: path/to/collection
id: doc-id

The field functions is an array describing your Firebase Cloud Functions that should be loaded and triggered by Foundry. All described functions must be exported in the function's root index.js file. In this array, you describe which functions should Foundry load and how it should trigger them every time you save your code.

It's important to understand how function triggers work in Foundry. Everything happens against the emulated Firestore database or the emulated Firebase Auth users. Both can be specified in the configuration file by fields firestore and users respectively. It's important to keep in mind that all of your code that manipulates with Firestore or Firebase Auth will actually interact with the emulated Firestore database and emulated Firebase Auth. You can "fill" the emulated Firestore and emulated users either with your custom data or with a copy of your production data. This way you won't accidentally change your production data but you still can debug & test your code and develop new features with the copy of your production data. The same is true for function triggers you describe in the Foundry configuration file. Triggers usually describe how should the emulated Firestore database or emulated users be mutated. In return, these mutations will trigger your functions as it would happen in the production environment.

If you don't specify how to trigger a Firestore or Auth function the function will still load but the code inside them won't run automatically every time you save your code.

To have Foundry only load a function but don't trigger it every time you save your code, omit the following fields:

  • If the type of a function is firestore omit the following fields:

    • updateDoc

    • createDoc

    • deleteDoc

  • If the type of a function is auth omit the following fields:

    • createUser

    • deleteUser

This comes handy in certain use cases where you want to simulate a logical flow in your app. Imagine you want to test an https function. This function changes a document inside your Firestore database in the collection myCollection. You also have anonUpdate Firestore function that is triggered every time there is an update to any document in the collection myCollection. One way to test this functionality during development would be having defined separate triggers for each function:

functions:
- name: myHttpsFunction
type: https
payload: {"data": "new document data"}
- name: myOnUpdateFunction
type: firestore
trigger: onUpdate
updateDoc:
collection: myCollection
id: doc-id
data: {"data": "new document data"}

The disadvantage of this approach is that both functions are triggered separately. This approach doesn't test the actual logical flow that will happen in the app on production.

Better approach would be to have only myHttpsFunction trigger automatically by specifying the payload filed and have Foundry only load the myOnUpdateFunction function without the updateDoc field. This way, Foundry won't trigger the myOnUpdateFunction manually but the function will get triggered by the actual mutation of an emulated Firestore database that was caused by code inside the myHttpsFunction.

functions:
- name: myHttpsFunction
type: https
payload: {"data": "new document data"}
# The 'myOnUpdateFunction' functions only loaded by Foundry
# but not triggered on every code change
- name: myOnUpdateFunction
type: firestore
trigger: onUpdate