Managing payments in your app: setting up inventory — the code
See how to implement item uploads to Cloud Firestore
Are you new to this series? Check out the first blog for an introduction and a table of contents!
Get caught up
If you’re interested in the rationale behind this code, you can find out all about it in the last post!
Assuming you already have read it, I’m basically going to dive into the implementation. To briefly summarize, we don’t want items to be hard-coded into our HTML. Instead, items will be stored in Cloud Firestore and downloaded when the website is accessed. But the items come with images — of course folks want to see what they’re going to buy! — so we need a place to store those as well. We use Cloud Storage to upload the item images, and then generate a unique download URL for each one so it can be viewed publicly.
Google Cloud Storage provides the perfect place to store sock pattern images
Get the project
Each step of the project can be found on GitHub. Download or clone the repo to follow along. Today, I’m walking through step 0: setting up inventory. Navigate to the part-0-set-up-inventory/upload-function folder and take a look at the contents.
- an
index.js
file - a
package.json
file - a
product_img
folder
The index.js
file contains the code to upload the inventory items. The package.json
file contains the Node.js packages we need. The product_img
folder contains the beautiful images of the socks.
Set up the project
Before we run the code, there are a couple of setup steps.
First, start with a new or existing Firebase project with Cloud Firestore initialized.
Then, install the required npm packages.
npm install
The function we use to upload the items uses the Firebase Admin SDK to access Cloud Firestore. In order to authenticate, you will need to download a service account key. Keep in mind that this allows access to all of your Firebase products, so be sure to keep it safe and never store it in a public repository.
Set the environment variable GOOGLE_APPLICATION_CREDENTIALS
to the file path of the JSON file that contains your service account key. This variable only applies to your current shell session, so if you open a new session, you will need to set the variable again, but this is unlikely to come into play since you only have to run this function once.
export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"
You’ll also need the name of your Cloud Storage bucket. You can hard-code this if you wish, but since we’ll need it for future parts of the project, I find it’s more convenient to create an environment variable.
export STORAGE_BUCKET="your-project-name.appspot.com"
Now the function is ready to be run! But before we run it, let’s take a look at what it does. It’s always good to know what you’re getting into!
First, we import and initialize the Firebase Admin SDK using those default credentials we just set in the terminal. Then, we create an instance of Firestore and an instance of your Cloud Storage bucket.
const admin = require('firebase-admin');
admin.initializeApp({
credential: admin.credential.applicationDefault(),
storageBucket: process.env.STORAGE_BUCKET
});
const db = admin.firestore();
const bucket = admin.storage().bucket();
Then, there is an array of the sock patterns.
let items = [
{
name: 'apple',
description: 'For the apple lover in your life',
price: 999
},
{
name: 'donut',
description: 'Some super sweet socks',
price: 999
},
{
name: 'stripes',
description: 'Classy and classic design',
price: 599
},
{
name: 'blue',
description: 'Simple, yet shockingly sophisticated',
price: 599
}
]
Next comes the setData()
function, which takes the array of the shop’s items and uploads the data to Cloud Firestore.
async function setData() {
for (item of items) {
console.log(item); // it’s fun to see something on the screen when you run a function
let thisItem = item;
const filename = `${item.name}.png`;
try {
// upload the image to Cloud Storage
await bucket.upload(`product_img/${filename}`, {
// Support for HTTP requests made with 'Accept-Encoding: gzip'
gzip: true,
metadata: {
cacheControl: ‘public, max-age=31536000’,
},
});
const config = {
action: 'read',
expires: '03–17–2025'
};
// get a signed URL so the image can be viewed publicly
const url = await bucket.file(filename).getSignedUrl(config);
// add URL to the data about the item
thisItem.images = url
// upload object data to Cloud Firestore
await db.collection(‘socks’).doc(item.name).set(thisItem);
} catch (error) {
console.error(error);
}
}
}
We also log the item names and objects so you have something to look at while running the function. Alright, without further ado, let’s run this!
node index.js
To ensure the inventory is successfully uploaded, check the Firebase Console.
Ta-da! And that was almost less work than adding the items from the console if you don’t count the time I spent coding it. But hey, it’s definitely less error-prone.
Next Steps
Now this is clearly not practical or convenient for making regular updates. What we really need is a frontend that makes adding items easier. We call that ‘foreshadowing’. But for now, this is what we need to get the project up and running!
Next:
- Check out all of Cloud Firestore’s capabilities in the guides
- View the next blog post
- See links to all posts in the first blog