Nous venons de voir comment exécuter localement les Google Cloud Functions. En développant des Firebase Functions, nous nous attendons à pouvoir utiliser les mêmes outils. Pourtant, en utilisant Firebase Storage (plutôt que Google Cloud Storage), le prototype de la fonction change sensiblement :

'use strict';

exports.fileUploaded = functions.storage.object().onChange(event => {
    const object = event.data;
    const filePath = object.name;

    // Exit if this is a deletion or a deploy event.
    if (object.resourceState === 'not_exists') {
        return console.log(`File ${filePath} deleted.`);
    } else if (!filePath) {
        return console.log('This is a deploy event.');
    } else {
        return console.log(`File ${filePath} uploaded.`);
    }
});

Si nous tentons d’invoquer la fonction via l’émulateur, nous obtiendrons le message d’erreur suivant :

$ functions call helloStorage --data='{"name":"myfolder/JarwWgSpjca4sUSSYFjP2jmKidH3/myfile.txt","bucket":"gs://my-project-bucket.appspot.com" }'
ExecutionId: 2e4646eb-0f97-4cde-815a-30281ae5d9d1
Error: { error:
   { code: 500,
     status: 'INTERNAL',
     message: 'Function worker crashed with exit code: 1
     undefinedC:\\Users\\pnom\\myproject\\functions\\node_modules\\firebase-functions\\lib\\config.js:51
        throw new Error(\'Firebase config variables are not available. \' +
        ^

Error: Firebase config variables are not available. Please use the latest version of the Firebase CLI to deploy this function.
    at init (C:\\Users\\pnom\\myproject\\functions\\node_modules\\firebase-functions\\lib\\config.js:51:15)
    at Object.config (C:\\Users\\pnom\\myproject\\functions\\node_modules\\firebase-functions\\lib\\config.js:29:9)
    at Object.object (C:\\Users\\pnom\\myproject\\functions\\node_modules\\firebase-functions\\lib\\providers\\storage.js:41:27)
    at Object.<anonymous> (C:\\Users\\pnom\\myproject\\functions\\index.js:14:42)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.require (module.js:497:17)',
     errors: [ 'Function worker crashed with exit code: 1\nundefinedC:\\Users\\pnom\\myproject\\functions\\node_modules\\firebase-functions\\lib\\config.js:51
        throw new Error(\'Firebase config variables are not available. \' +
        ^

Error: Firebase config variables are not available. Please use the latest version of the Firebase CLI to deploy this function.
    at init (C:\\Users\\pnom\\myproject\\functions\\node_modules\\firebase-functions\\lib\\config.js:51:15)
    at Object.config (C:\\Users\\pnom\\myproject\\functions\\node_modules\\firebase-functions\\lib\\config.js:29:9)
    at Object.object (C:\\Users\\pnom\\myproject\\functions\\node_modules\\firebase-functions\\lib\\providers\\storage.js:41:27)
    at Object.<anonymous> (C:\\Users\\pnom\\myproject\\functions\\index.js:14:42)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.require (module.js:497:17)' ] } }

Même après avoir mis à jour la dernière version du CLI Firebase, nous avons toujours ce message d’erreur…

Heureusement, Firebase propose une autre méthode pour exécuter localement les fonctions Firebase.

Installation

Pour cela, il faut utiliser l’outil firebase-tools en version 3.11.0 minimum et un SDK en 0.6.2 minimum. L’installation des dépendances se fait ainsi :

# installation des outils
$ npm install -g firebase-tools

# installation du SDK (depuis la racine du répertoire projet)
$ cd functions
$ npm install --save firebase-functions@latest

Utilisation

Ensuite, il suffit de démarrer le Cloud Function Shell :

$ firebase experimental:functions:shell
i  functions: Preparing to emulate functions.
+  functions: helloStorage
firebase > var data = {name:"myfolder/JarwWgSpjca4sUSSYFjP2jmKidH3/myfile.txt",bucket:"gs://my-project-bucket.appspot.com"};
undefined
firebase > helloStorage(data);
'Successfully invoked function.'
firebase > info: User function triggered, starting execution
info: File myfolder/JarwWgSpjca4sUSSYFjP2jmKidH3/myfile.txt uploaded.
info: Execution took 15 ms, user function completed successfully

firebase > 

Conclusion

Tous ces outils semblent encore assez jeunes. Il faut une version du Firebase CLI relativement récente. Et le moindre petit grain de sable pourra vous faire perdre quelques heures…

De plus, j’ai été incapable de démarrer le serveur local Firebase en mode exécution de fonction qui est sensé proposer la même interface que Cloud Function Shell1.
De même, je n’ai pas réussi à exécuter localement une fonction qui télécharge depuis Firebase Storage ou qui envoie un fichier vers ce même service 2.

Au final, même si le service de fonctions est la pièce angulaire à tous ces autres services, force est de constater que son outillage doit encore progresser. Un écosystème à surveiller donc !

  1. Via la commande firebase serve --only functions.
  2. Alors que la fonction s’exécute correctement sur les serveurs de Firebase !