Extensions
Firenook runs the Extensions instances listed in your firebase.json as
extra Functions backends, with the official emulator’s rules for their
parameters, specs and triggers. Read this page to see where their code comes
from, how to make them start with no network and no login, and what is not
supported.
Where an instance’s code comes from
Section titled “Where an instance’s code comes from”Instances are listed as the official CLI lists them:
{ "extensions": { "search": "algolia/firestore-algolia-search@1.2.10", "thumbnails": "./extensions-src/thumbnails" }}extensions counts as Functions, so the Functions port serves them and
--only functions includes them. Firenook looks for each instance’s code in
this order:
| Source | Where | Needs network |
|---|---|---|
| Local | The path you wrote, read from disk | No |
| Vendored | extensions/.sources/<publisher>/<name>@<version> in your project |
No |
| Cached | The firebase-tools cache, ~/.cache/firebase/extensions (or FIREBASE_EXTENSIONS_CACHE_PATH) |
No |
| Registry | Downloaded once, then built with npm install and npm run gcp-build |
Yes, and a login |
Parameters come from extensions/<instance>.env, .env.<alias>,
.env.<projectId>, .env.local and .secret.local, with the official
precedence, defaults and ${param:X} substitution. While the suite runs, a
change to an instance’s parameter files reloads that instance; a change that
does not load is logged with its error.
Start offline with ext:vendor
Section titled “Start offline with ext:vendor”firenook ext:vendor copies each resolved source into the project and
records how unpinned references resolved, so every later start reads it from
there:
$ npx firenook ext:vendorsearch: vendored algolia/firestore-algolia-search@1.2.10 at ./extensions/.sources/algolia/firestore-algolia-search@1.2.10Commit extensions/.sources/ and your teammates and CI start the same
Extensions with no network and no Firebase login. firenook doctor shows, for
every instance, where its source comes from and whether it starts offline:
{ "instanceId": "search", "written": "algolia/firestore-algolia-search@1.2.10", "kind": "registry", "version": "1.2.10", "source": "vendored", "offlineReady": true, "paramsFound": true, "note": null}An instance with no vendored or cached source reads "offlineReady": false
and the note no vendored or cached source; the first start downloads it (network and a Firebase CLI login or FIREBASE_TOKEN).
firenook ext:vendor --offline never contacts the registry: it copies only
what the shared cache already holds, with its firenook-registry.json, and
names what it could not copy:
$ npx firenook ext:vendor --offlinefirenook extensions: counter (firebase/firestore-counter@0.2.10) could not be vendored: firebase/firestore-counter@0.2.10 is not vendored under ~/demo-shop/extensions/.sources/firebase/firestore-counter@0.2.10 and not in the cache at ~/.cache/firebase/extensions/firebase/firestore-counter@0.2.10; run `firenook ext:vendor` with network accessTo make sure nothing is fetched, start with --offline (or set
FIRENOOK_OFFLINE=1). An instance that would need the registry then stops the
start and says what to do:
suite failed: Extensions failed to load: firebase/storage-resize-images@0.2.10 is not vendored under ./extensions/.sources/firebase/storage-resize-images@0.2.10 and not in the cache at ~/.cache/firebase/extensions/firebase/storage-resize-images@0.2.10; run `firenook ext:vendor` with network accessWhat needs a login
Section titled “What needs a login”Only the registry. To read an Extension’s metadata and, the first time, its
source archive, Firenook uses the Firebase CLI’s stored login or a
FIREBASE_TOKEN refresh token, the same credential the official emulator
uses. It reads the login where the Firebase CLI writes it:
$XDG_CONFIG_HOME/configstore/firebase-tools.json, else
~/.config/configstore/firebase-tools.json, with ~ your home folder
(%USERPROFILE% on Windows). It then keeps the registry’s answers next to
the source (firenook-registry.json), so later starts stay offline. A source
vendored or cached under Firenook’s former name keeps its old file and still
starts offline. Local, vendored and
cached instances need no login at all; Without a Google
login covers working that way.
Secret Manager is never contacted. Put secret parameters in
extensions/<instance>.secret.local.
What it does not run
Section titled “What it does not run”-
Lifecycle tasks (
onInstall,onUpdate,onConfigure): an Extension’s task-queue functions are not delivered, as on the official emulator. -
Triggers for a service the suite does not emulate or does not start. The whole instance is left out, with the official emulator’s lines. Here
--only functionsleaves out Firestore:firenook extensions[audit]: ignored becuase it includes firestore triggered functions, and the firestore emulator does not exist or is not running.firenook extensions: No Cloud Functions for these instances will be emulated, because partially emulating an Extension can lead to unexpected behavior. -
Dynamic Extensions defined in your Functions code, and Extensions written in Python or Dart.
-
Secret Manager, as above.
- Cloud Functions: the runtime Extensions share.
- Eventarc: events an Extension publishes.
- CI and GitHub Actions: vendored Extensions in CI.