-
Notifications
You must be signed in to change notification settings - Fork 12
LAB7_Implement a CRUD Api in Astra
Objectives
In this step, we will:
- Create test cases to check that our API call is working correctly
- Build the API call to Astra to create a game document, based on the requirements from our test
We will cover:
- Creating the
insertGame
Netlify endpoint - Connect to Astra
- Hook it all together
- Running TDD tests
- Verify document creation
Now that we have ALLLLL of our environment vars set and our game document store, let's start building our basic insertGame
serverless function, in the function/insertGame.js
file.
First, we need to declare gameId
and gamePayload
variables. We know each game is associated with it's own unique game id, and during game play we can anticipate getting a payload from the user.
From Netlify, you get your gameId
parameter from the path of the incoming REST call, and parse our event body that is associated with it as the gamePayload
.
By default, Netlify puts your function at the path /.netlify/function/insertGame
.
In the following sections you will be given code to copy into the stubbed out insertGame.js
file.
📘 Code to copy
// let's set the game id
gameId = event.path.split("insertGame/")[1];
// let's parse the incoming payload
gamePayload = JSON.parse(event.body);
Let's not forget about error handling. If we cannot parse the game id or body from the incoming REST call, a HTTP status code of 400
will be returned and you will get an error message
📘 Code to copy
// let's return a 400 if we can't parse the game id or body
return {
statusCode: 400,
body: JSON.stringify({ message: "must provide a valid game ID" }),
};
All this should satisfy our second test (i.e. we need to get valid game id)
The next thing we need to do is to connect to our Astra database. We are first going to import the JavaScript SDK library (astrajs
) to create our Astra Client. We are going to give the Astra client our environment variable credentials to connect to the database, and create a document to store information about our game.
Go HERE for more information on the JavaScript SDK library.
📘 Code to copy
// let's connect to Astra
const astraClient = await createClient({
// let's set our Astra connection configuration
astraDatabaseId: process.env.ASTRA_DB_ID,
astraDatabaseRegion: process.env.ASTRA_DB_REGION,
username: process.env.ASTRA_DB_USERNAME,
password: process.env.ASTRA_DB_PASSWORD,
});
const gamesCollection = astraClient
.namespace(process.env.ASTRA_DB_KEYSPACE)
.collection(process.env.GAMES_COLLECTION);
These variables should look really familiar. They are the same exact environment variables we just set in both GitHub secrets and Netlify environment variables. THESE are what make the connection between our data layer, our CI/CD pipeline, and our production deployment.
Finally, we are going to try to take all our configuration information stored in gamesCollection
and provision a new game from it. If it works, we get back a HTTP status code of 200
. If it fails, we will get back a 500
.
This should satisfy both test 1 and test 2 defined in the next section.
📘 Code to copy
// let's provision a new game
try {
// let's create a new game with the gamesCollection
const res = await gamesCollection.create(gameId, gamePayload);
// let's return a 200 with the resoponse from astra
return {
statusCode: 200,
body: JSON.stringify(res),
};
} catch (e) {
console.error(e);
// let's return a 500 on error
return {
statusCode: 500,
body: JSON.stringify(e),
};
}
For a FULL code solution to this section right-click
the image below and choose Open Link in New Tab
.
const { createClient } = require("@astrajs/collections");
exports.handler = async (event, context) => {
// Step 1: let's return a 400 if we don't recieve a valid game id
let gameId;
let gamePayload;
try {
// let's set the game id
gameId = event.path.split("insertGame/")[1];
// let's parse the incoming payload
gamePayload = JSON.parse(event.body);
} catch (e) {
// let's return a 400 if we can't parse the game id or body
return {
statusCode: 400,
body: JSON.stringify({ message: "must provide a valid game ID" }),
};
}
// Step 1: let's connect to Astra
const astraClient = await createClient({
// let's set our Astra connection configuration
astraDatabaseId: process.env.ASTRA_DB_ID,
astraDatabaseRegion: process.env.ASTRA_DB_REGION,
username: process.env.ASTRA_DB_USERNAME,
password: process.env.ASTRA_DB_PASSWORD,
});
const gamesCollection = astraClient
.namespace(process.env.ASTRA_DB_KEYSPACE)
.collection(process.env.GAMES_COLLECTION);
// Step 1: let's provision a new game
try {
// let's create a new game with the gamesCollection
const res = await gamesCollection.create(gameId, gamePayload);
// let's return a 200 with the resoponse from astra
return {
statusCode: 200,
body: JSON.stringify(res),
};
} catch (e) {
console.error(e);
// let's return a 500 on error
return {
statusCode: 500,
body: JSON.stringify(e),
};
}
};
The way we approach testing is by asking the question "What does our endpoint need to do?". We want our serverlesss function to provision a new game on Astra -- and we need provide the API with a random game code so this can work. Our endpoint needs to:
- Tell the API to make the game document
- It should not be able to make a game document if we don't give it a valid game id
- If we get a 500 on error (something goes wrong), we should be informed
We are provided with test cases test/insertGame.test.js
that will check for these actions working in functions/insertGame.js
. Notice that insertGame
is required as a dependency in our test.js
file.
We are going to use faker.js
, a JavaScript library for generating mock data. This mock data is useful when building and testing our application. Hence, we should require
the faker library.
TEST 1: Our API should make the game document. We need to test to see if the insertGame
function actually does that:
We use a simple async function to do this. faker.helpers.replaceSymbols("????")
will create a sample game id for the path, and some user data in the
body. As successful test run will return a 200
.
TEST 2 : Our function must not be able to create a game document with a valid game id
We ensure that our function cannot go ahead and create a game, unless it has been provided with a valid game id.
Some of you may have noticed .skip
in both of the insertGame.test.js
tests. If we are going to run these tests we obviously don't want to skip them. Remove .skip
from both examples in order to ensure our insertGame tests run.
Once complete your tests should look like this.
You might be curious why we added .skip
in the first place. Per regular TDD development processes we start with tests, then create code based off of those tests. We already had the test cases implemented for you. The code wasn't ready until you just completed it a moment ago so now we are ready to move forward and run our tests.
Now let's run our tests to see if our function works.
📘 Command to execute
npm run test:functions
📗 Expected output
Ok, last part for this section. If our tests were successful we should now have document data in our database. Let's go check and see if that was the case.
Open Astra UI, show the CQL Console
and execute the following command (here battlestax
is your keyspace and games
your collection name - if you chose another names adapt the query accordingly).
📘 Command to execute
SELECT key, text_value FROM battlestax.games;
You should have a result that looks like the following image. If you see the game you just created in this list you know your application is properly hooked up to your database via the document API.
If you are curious run the tests again and then execute the above query once more. You should see a new entry every time you run a test.
🏠 Home
Introduction to the JAMStack Why this is cool ? Introduction to Netlify Want to learn more ? 🛠️ II - Setup and deploy your first app
Create your BattleStax repository Setup Netlify account Summary 🛠️ III - Create your Astra instance
Register and Sign In to Astra Configure and create your database Activate Cassandra awesome 📚 IV - What can Netlify do for you
Build, Package, deploy, host Advanced features Netlify Functions Want to learn more 🛠️ V - Expose your "hello world" API
Setup your environment Make a serverless endpoint using Netlify functions Merge back to master Check your deployment in Netlify Summary 📚 VI - What are DataStax Astra and Stargate
Introduction to Astra Introduction to Stargate Want to know More 🛠️ VII - Set environment variables in your application
Creating the .env file Explore the API with HTTPie 🛠️ VIII - Set secrets in GitHub for CI/CD
Configure secrets in GitHub Verify your secrets How is this all working ? 🛠️ IX - Set environment variables in Netlify
Set environment variables in Netlify Verify your environment variables Summary 🛠️ X - Implement a CRUD Api in Astra
Creating the insertGame Netlify endpoint Connect to Astra Hook it all together Running TDD tests 🛠️ XI - Verify and Deploy in Netlify
Merge back to master Verify your deployment in Netlify Feel the enormity of your accomplishment Super secret full game option 📚 XII - Resources