A long while back, David East wrote a handy blog post about using the Firebase CLI to read and write your Firebase Realtime Database. The CLI has evolved a lot since then, so I'd like to share some of what's changed (and new!).
When I first started working with Realtime Database, I'd spend a fair amount of time in the Firebase console manually entering some data to work with. It's kinda fun to make changes there, then see them immediately in my app! But I soon discovered that it's kind of repetitive and time consuming to test like that. Instead, I could write a program to make the changes for me, but that wasn't a very flexible option. For easy reading and writing of data in my database, I found that the Firebase CLI is the best option for me. So, I'll share some of what it does here and how it can come in handy. All my examples will be using the Bash shell - you may have to modify them for other shells.
The Firebase CLI requires you to set aside a project directory, log in, and select a project that you want to work with, so be sure to follow the instructions to get set up with your existing project.
To write data from the command line use the firebase database:set command:
firebase database:set
firebase database:set /import data.json
The first argument to database:set is the path within the database to be written (here, /import), and the second is the JSON file to read from. If you don't have a file, and would rather provide the JSON on the command line, you can do this also with the --data flag:
/import
--data
firebase database:set /import --data '{"foo": "bar baz"}'
Notice that the JSON is quoted for the command line with single quotes. Otherwise, the space between the colon and "bar" would fool your shell into thinking that there are two arguments there. You can't use double quotes to quote this JSON string either, because JSON uses those quotes for its own strings. Escaping JSON for a unix command line can be tricky, so be careful about that! (For further thought: what if there was a single quote in one of the JSON strings?)
Also, you can pipe or redirect JSON to stdin. So, if you have a program that generates some JSON to add to your database, you can do it like this:
echo '{"foo": "bar baz"}' | firebase database:set /import --confirm
Notice that the --confirm flag is passed here to prevent the command from asking if you're OK potentially overwriting data. Piping to stdin won't work without it!
--confirm
The database:set command is great for initially populating your database with a setup script. If you run automated integration tests, the CLI is a handy way of scripting the initialization of your test environment.
database:set
It's also super handy for quickly triggering Cloud Functions database triggers, so you don't have to type in stuff at the command prompt every time you have something complicated to test.
Reading data from your database with the Firebase CLI is similarly easy. Here's how you fetch all the data under /messages as a JSON blob:
/messages
firebase database:get /messages
To save the output to a file, you can use a shell redirect, or the --output flag:
firebase database:get /messages > messages.json firebase database:get /messages --output messages.json
You'll notice the JSON output is optimized for space, which makes it hard to read. For something a little easier on the eyes, you can have the output "pretty-printed" for readability:
firebase database:get /messages --pretty
You can also sort and limit data just like the Firebase client APIs.
firebase database:get /messages --order-by-value date
To see all the options for reading and sorting, be sure to see the CLI help (all Firebase CLI commands share their usage like this):
firebase database:get --help
You've probably used the Realtime Database push function to add data to a node in your database. You can do the same with the CLI:
firebase database:push /messages --data '{"name":"Doug","text":"I heart Firebase"}'
This will create a unique push id under /messages and add the data under it. (Did you know that push IDs recently switched from starting with "-K" to "-L"?)
If you want to update some values at a location without overwriting that entire location, use database:update:
database:update
firebase database:update /users/-L-7Zl_CiHW62YWLO5I7 --data '{"name":"CodingDoug"}'
For those times when you need to remove something completely, there is database:remove. This command will blow away your entire database, unconditionally, kinda like rm -rf /. Be careful with this one:
database:remove
rm -rf /
firebase database:remove / --confirm
Sometimes you might want to simply copy the contents of your database from one project to another (for example, your development environment to staging). This is really easy by piping the stdout of database:get to the stdin of database:set:
database:get
firebase --project myproject-dev database:get / | \ firebase --project myproject-staging database:set / --confirm
Note here the use of --project to specify which Firebase project is to be used for reading and writing. This is your project's unique id in the Firebase console.
--project
If you find yourself repeating a set of commands, it's probably time to make a bash function. Save your function to your .bash_profile and you'll be able to access them from anywhere in your shell command line.
Do you often copy data between databases? The function below makes it easy:
function transfer_to() { local src_db="${1}" local dest_db="${2}" local path="${3:-/}" firebase database:get --project "$src_db" "$path" | firebase --project "$dest_db" database:set "$path" --confirm }
To use the function just call the transfer_to command (as if it were any other command) with the names of the project to copy to and from:
transfer_to myproject-dev myproject-staging
The command line is one of the most versatile tools in an engineer's toolbox. What are you doing with the CLI? We'd love to hear from you, so please shout out to us on Twitter. If you have any technical questions, post those on Stack Overflow with the firebase tag. And for bug reports and feature requests, use this form.