Connect server code
Server code finds the emulators through environment variables, which the
Admin SDKs and Google’s Cloud client libraries read when they start. Run the
code with firenook emulators:exec and it sets them for you, or set them
yourself for a server you start on its own.
Let emulators:exec set them
Section titled “Let emulators:exec set them”npx firenook emulators:exec -- node scripts/seed.jsnpx firenook emulators:exec "npm test"emulators:exec starts the emulators, runs the command once they are ready,
then stops them and exits with the command’s exit code. The command gets the
variables the official emulators:exec sets, for the emulators that run and
no others:
| Variable | Value with the default ports | Set when |
|---|---|---|
FIRESTORE_EMULATOR_HOST, FIREBASE_FIRESTORE_EMULATOR_ADDRESS |
127.0.0.1:8080 |
Firestore runs |
FIREBASE_AUTH_EMULATOR_HOST |
127.0.0.1:9099 |
Auth runs |
FIREBASE_STORAGE_EMULATOR_HOST |
127.0.0.1:9199 |
Storage runs |
STORAGE_EMULATOR_HOST |
http://127.0.0.1:9199 |
Storage runs |
PUBSUB_EMULATOR_HOST |
127.0.0.1:8085 |
Pub/Sub runs |
CLOUD_TASKS_EMULATOR_HOST |
127.0.0.1:9499 |
Functions run |
CLOUD_EVENTARC_EMULATOR_HOST |
http://127.0.0.1:9299 |
Functions run |
FIREBASE_EMULATOR_HUB |
127.0.0.1:4400 |
Always |
GCLOUD_PROJECT, GOOGLE_CLOUD_PROJECT |
The project id | Always |
GOOGLE_APPLICATION_CREDENTIALS |
Demo credentials in the run’s folder | Unless you set it |
CLOUDSDK_CONFIG |
A path in the run’s folder, where gcloud finds no login of yours | Always |
The demo credentials keep the SDKs away from your own Google login, and
none of them sends a token request to Google: the file holds the emulators’
own token, and names the hub as the place to refresh it. A Node.js SDK
refreshes at Google whatever the file says, so emulators:exec also adds a
--require of its token helper to NODE_OPTIONS, which answers that request
in each Node.js process of the command. Each run’s folder is under
.firenook/runs/.
When your environment already sets GOOGLE_APPLICATION_CREDENTIALS,
emulators:exec keeps it, as the official command does, and writes no demo
credentials. Run your tests
has the details.
Set them yourself
Section titled “Set them yourself”For a server you run next to firenook emulators:start, such as a dev
server in another terminal, export the variables first:
export FIRESTORE_EMULATOR_HOST=127.0.0.1:8080export FIREBASE_AUTH_EMULATOR_HOST=127.0.0.1:9099export FIREBASE_STORAGE_EMULATOR_HOST=127.0.0.1:9199export STORAGE_EMULATOR_HOST=http://127.0.0.1:9199export PUBSUB_EMULATOR_HOST=127.0.0.1:8085export GCLOUD_PROJECT=demo-shopOr put them in the .env file your framework loads in development. Use the
ports from your firebase.json if they are not the defaults; the console’s
Connect dialog prints these lines, under Environment variables, with
yours filled in. The project id must be the one Firenook runs with.
Never set them in production. With FIREBASE_AUTH_EMULATOR_HOST set, the
Admin SDKs accept unsigned ID tokens, which the Auth emulator issues.
Node.js
Section titled “Node.js”The Admin SDK for Node.js reads FIRESTORE_EMULATOR_HOST,
FIREBASE_AUTH_EMULATOR_HOST and FIREBASE_STORAGE_EMULATOR_HOST, and needs
no credentials when they are set:
import { initializeApp } from 'firebase-admin/app'import { getAuth } from 'firebase-admin/auth'import { getFirestore } from 'firebase-admin/firestore'import { getStorage } from 'firebase-admin/storage'
initializeApp({ projectId: 'demo-shop', storageBucket: 'demo-shop.appspot.com' })
const user = await getAuth().createUser({ email: 'ada@example.com', password: 'secret-pass' })await getFirestore().doc(`users/${user.uid}`).set({ name: 'Ada' })await getStorage().bucket().file('reports/today.txt').save('hello')npx firenook emulators:exec -- node scripts/seed.jscreateCustomToken works too: with the Auth emulator, the SDK signs nothing,
and the client SDK connected to the same emulator accepts the token.
Python
Section titled “Python”The Admin SDK for Python reads FIRESTORE_EMULATOR_HOST and
FIREBASE_AUTH_EMULATOR_HOST. Its storage module does not read
FIREBASE_STORAGE_EMULATOR_HOST: the Cloud Storage library under it reads
STORAGE_EMULATOR_HOST, a URL with http://. The SDK also looks for default
credentials when it starts. Run it with emulators:exec, which sets all of
these:
import firebase_adminfrom firebase_admin import auth, firestore, storage
firebase_admin.initialize_app(options={"projectId": "demo-shop", "storageBucket": "demo-shop.appspot.com"})
user = auth.create_user(email="ada@example.com", password="secret-pass")firestore.client().document(f"users/{user.uid}").set({"name": "Ada"})storage.bucket().blob("reports/today.txt").upload_from_string("hello")npx firenook emulators:exec -- python seed.pyTo run it on its own, next to firenook emulators:start, set the variables
and point GOOGLE_APPLICATION_CREDENTIALS at a demo credentials file like
the one emulators:exec writes. It holds the emulators’ own token, which the
SDK uses as it is, so it never asks Google for one. With the default hub
port:
{"type":"authorized_user","client_id":"demo","client_secret":"demo","refresh_token":"demo","token_uri":"http://127.0.0.1:4400/firenook/oauth2/token","token":"owner","expiry":"2999-12-31T23:59:59Z"}export GOOGLE_APPLICATION_CREDENTIALS=demo-credentials.jsonexport FIRESTORE_EMULATOR_HOST=127.0.0.1:8080export FIREBASE_AUTH_EMULATOR_HOST=127.0.0.1:9099export STORAGE_EMULATOR_HOST=http://127.0.0.1:9199python seed.pyThe console’s Connect dialog prints the Python lines with your ports and this file’s content filled in.
The Admin SDK for Go reads FIRESTORE_EMULATOR_HOST and
FIREBASE_AUTH_EMULATOR_HOST, and copies FIREBASE_STORAGE_EMULATOR_HOST
into STORAGE_EMULATOR_HOST when that is not set. Run the program with
emulators:exec, or set the variables and the demo credentials file
yourself:
app, err := firebase.NewApp(ctx, &firebase.Config{ ProjectID: "demo-shop", StorageBucket: "demo-shop.appspot.com",})npx firenook emulators:exec -- go run .A Java program cannot change its own environment, so the variables, and
GOOGLE_APPLICATION_CREDENTIALS pointing at the demo credentials file, must
be set before the JVM starts. emulators:exec does that for the command it
runs. Java’s Storage and Pub/Sub clients read no emulator variable, so build
them on the emulator; the console’s Java snippet shows how.
FirebaseOptions options = FirebaseOptions.builder() .setProjectId("demo-shop") .setStorageBucket("demo-shop.appspot.com") .setCredentials(GoogleCredentials.getApplicationDefault()) .build();FirebaseApp.initializeApp(options);npx firenook emulators:exec -- ./gradlew runGoogle Cloud client libraries
Section titled “Google Cloud client libraries”Google’s Cloud client libraries read the same variables: the Firestore
libraries FIRESTORE_EMULATOR_HOST, the Cloud Storage libraries
STORAGE_EMULATOR_HOST, and the Pub/Sub libraries PUBSUB_EMULATOR_HOST.
With Pub/Sub, for example, no code changes:
import { PubSub } from '@google-cloud/pubsub'
const pubsub = new PubSub({ projectId: 'demo-shop' })const [topic] = await pubsub.createTopic('orders')const [subscription] = await topic.createSubscription('orders-worker')await topic.publishMessage({ json: { orderId: 'A-1001' } })subscription.once('message', async (message) => { console.log(message.data.toString()) message.ack() await subscription.close() await pubsub.close()})PUBSUB_EMULATOR_HOST=127.0.0.1:8085 node scripts/publish.jsWith PUBSUB_EMULATOR_HOST set, the library needs no credentials.
Cloud Tasks and Eventarc
Section titled “Cloud Tasks and Eventarc”The Admin SDK sends task queue calls to CLOUD_TASKS_EMULATOR_HOST
(127.0.0.1:9499, no scheme) and Eventarc events to
CLOUD_EVENTARC_EMULATOR_HOST (http://127.0.0.1:9299, with the scheme).
Firenook gives both to your Functions, and emulators:exec sets both for its
command when Functions run. A script you run on its own sets them itself.
The Node.js SDK reaches both, and Python’s reaches Cloud Tasks. An Eventarc
publish from Node.js asks for an access token first: under emulators:exec
it gets the emulators’ own; run on its own, it asks your default
credentials. See Cloud Tasks and
Eventarc.
Run your tests with emulators:exec, or run them
in CI.