This sample app shows how to use Fauna in a production application.
The app uses Node.js and the Fauna v10 JavaScript driver to create HTTP API endpoints for an e-commerce store. You can use the app's API endpoints to manage products, customers, and orders for the store.
The app uses Fauna schemas and queries to:
-
Read and write data with strong consistency.
-
Define and handle relationships between resources, such as linking orders to products and customers.
-
Validate data changes against business logic.
The app's source code includes comments that highlight Fauna best practices.
The sample app uses the following Fauna features:
-
Document type enforcement: Collection schemas enforce a structure for the app's documents. Fauna rejects document writes that don't conform to the schema, ensuring data consistency. Zero-downtime migrations let you safely change the schemas at any time.
-
Relationships: Normalized references link documents across collections. The app's queries use projection to dynamically retrieve linked documents, even when deeply nested. No complex joins, aggregations, or duplication needed.
-
Computed fields: Computed fields dynamically calculate their values at query time. For example, each customer's
orders
field uses a query to fetch a set of filtered orders. Similarly, each order'stotal
is calculated at query time based on linked product prices and quantity. -
Constraints: The app uses constraints to ensure field values are valid. For example, the app uses unique constraints to ensure each customer has a unique email address and each product has a unique name. Similarly, check constraints ensure each customer has only one cart at a time and that product prices are not negative.
-
User-defined functions (UDFs): The app uses UDFs to store business logic as reusable queries. For example, the app uses a
checkout()
UDF to process order updates.checkout()
calls another UDF,validateOrderStatusTransition()
, to validatestatus
transitions for orders.
To run the app, you'll need:
-
A Fauna account. You can sign up for a free account at https://dashboard.fauna.com/register.
-
Node.js v20.x or later
-
Fauna CLI v3.0.0 or later.
To install the CLI, run:
npm install -g fauna-shell@latest
You should also be familiar with basic Fauna CLI commands and usage. For an overview, see the Fauna CLI docs.
-
Clone the repo and navigate to the
js-sample-app
directory:git clone [email protected]:fauna/js-sample-app.git cd js-sample-app
-
Log in to Fauna using the Fauna CLI:
fauna cloud-login
When prompted, enter:
- Endpoint name:
cloud
(Press Enter) - Email address: The email address for your Fauna account.
- Password: The password for your Fauna account.
- Which endpoint would you like to set as default? The
cloud-*
endpoint for your preferred region group. For example, to use the US region group, usecloud-us
.
The command requires an email and password login. If you log in to Fauna using GitHub or Netlify, you can enable email and password login using the Forgot Password workflow.
- Endpoint name:
-
Use the Fauna CLI to create the
ECommerce
database:fauna create-database ECommerce
-
Create a
.fauna-project
config file for the project:fauna project init
When prompted, enter:
schema
as the schema directory.dev
as the environment name.- The default endpoint.
ECommerce
as the database.
-
Push the
.fsl
files in theschema
directory to theECommerce
database:fauna schema push
When prompted, accept and stage the schema.
-
Check the status of the staged schema:
fauna schema status
-
When the status is
ready
, commit the staged schema to the database:fauna schema commit
The commit applies the staged schema to the database. The commit creates the collections and user-defined functions (UDFs) defined in the
.fsl
files of theschema
directory. -
Create a key with the
server
role for theECommerce
database:fauna create-key --environment='' ECommerce server
Copy the returned
secret
. The app can use the key's secret to authenticate requests to the database. -
Make a copy of the
.env.example
file and name the copy.env
. For example:cp .env.example .env
-
In
.env
, set theFAUNA_SECRET
environment variable to the secret you copied earlier:... FAUNA_SECRET=fn... ...
The app includes tests that check the app's API endpoints and create related documents
in the ECommerce
database.
From the root directory, run:
npm install && npm run test
You can view documents created by the tests in the Fauna Dashboard.
The app runs an HTTP API server. From the root directory, run:
npm install && npm run dev
Once started, the local server is available at http://localhost:8000.
The app's HTTP API endpoints are defined in *.controller.ts
files in the
src/routes
directory.
Reference documentation for the endpoints is available at https://fauna.github.io/js-sample-app/.
You can use the endpoints to make API requests that read and write data from
the ECommerce
database.
For example, with the local server running in a separate terminal tab, run the
following curl request to the POST /products
endpoint. The request creates a
Product
collection document in the ECommerce
database.
curl -v \
http://localhost:8000/products \
-H "Content-Type: application/json" \
-d '{
"name": "The Old Man and the Sea",
"price": 899,
"description": "A book by Ernest Hemingway",
"stock": 10,
"category": "books"
}'
You can further expand the app by adding fields and endpoints.
As an example, the following steps adds a computed totalPurchaseAmt
field to
Customer documents and related API responses:
-
If you haven't already, add the sample data:
npm install && npm run test
-
In
schema/collections.fsl
, add the followingtotalPurchaseAmt
computed field definition to theCustomer
collection:collection Customer { ... // Use a computed field to get the set of Orders for a customer. compute orders: Set<Order> = (customer => Order.byCustomer(customer)) + // Use a computed field to calculate the customer's cumulative purchase total. + // The field sums purchase `total` values from the customer's linked Order documents. + compute totalPurchaseAmt: Number = (customer => customer.orders.fold(0, (sum, order) => { + let order: Any = order + sum + order.total + })) ... } ...
Save
schema/collections.fsl
. -
Push the updated schema to the
ECommerce
database:fauna schema push
When prompted, accept and stage the schema.
-
Check the status of the staged schema:
fauna schema status
-
When the status is
ready
, commit the staged schema changes to the database:fauna schema commit
-
In
src/routes/customers/customers.controller.ts
, add thetotalPurchaseAmt
field to thecustomerResponse
FQL template:// Project Customer document fields for consistent responses. const customerResponse = fql` customer { id, name, email, + totalPurchaseAmt, address } `;
Save
src/routes/customers/customers.controller.ts
.Customer-related endpoints use this template to project Customer document fields in responses.
-
Start the app server:
npm install && npm run dev
-
With the local server running in a separate terminal tab, run the following curl request to the
POST /customers
endpoint:curl -v http://localhost:8000/customers/999
The response includes the computed
totalPurchaseAmt
field:{ "id": "999", "name": "Valued Customer", "email": "[email protected]", "totalPurchaseAmt": 27000, "address": { "street": "123 Main St", "city": "San Francisco", "state": "CA", "postalCode": "12345", "country": "United States" } }