diff --git a/.github/workflows/validate-openapi.yml b/.github/workflows/validate-openapi.yml new file mode 100644 index 0000000..852074c --- /dev/null +++ b/.github/workflows/validate-openapi.yml @@ -0,0 +1,23 @@ +name: Validate OpenAPI Spec + +on: + push: + paths: + - "openapi.yml" + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install dependencies + run: npm ci + + - name: Validate OpenAPI spec + run: npm run lint:openapi diff --git a/docs/index.html b/docs/index.html index 088fe4d..366f70c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,756 +1,24 @@ + + Redoc + + + + - - - Fauna JavaScript sample app - - - - - - - - - -

Fauna JavaScript sample app (1.0.0)

Download OpenAPI specification:Download

HTTP API reference documentation for the Fauna JavaScript sample -app.

-

The app uses Fauna and Node.js to create HTTP API endpoints for a sample -e-commerce store. You can use the endpoints to manage customers, -products, and orders for the store.

-

For an overview and more details, see the -README.

-

Authentication

Requests to the endpoints require no authentication. Internally, requests to -Fauna are authenticated using a Fauna key's secret. You pass the secret -using the FAUNA_SECRET environment variable in .env.

-

For setup instructions, see the -README.

-

Customers

Get, create, and update customers for the e-commerce store.

-

Create a customer.

Create a customer with the specified details.

-
Request Body schema: application/json
required
name
required
string

Customer name

-
email
required
string <email>

Customer's email address. Must be unique.

-

Internally, the Customer collection uses a unique constraint to -ensure email values are unique across customers.

-
required
object

Customer's mailing address.

-

Responses

Request samples

Content type
application/json
{
  • "name": "John Doe",
  • "email": "john.doe@example.com",
  • "address": {
    }
}

Response samples

Content type
application/json
{
  • "id": "111",
  • "name": "John Doe",
  • "email": "john.doe@example.com",
  • "address": {
    }
}

Get a customer.

Fetch the details of a customer by their ID.

-
path Parameters
id
required
string

ID of the customer to retrieve.

-

Responses

Request samples

curl -v http://localhost:8000/customers/111

Response samples

Content type
application/json
{
  • "id": "111",
  • "name": "John Doe",
  • "email": "john.doe@example.com",
  • "address": {
    }
}

Update a customer.

Update the details of a customer by their ID.

-
path Parameters
id
required
string

ID of the customer to update.

-
Request Body schema: application/json
required
name
required
string

Customer name

-
email
required
string <email>

Customer's email address. Must be unique.

-

Internally, the Customer collection uses a unique constraint to -ensure email values are unique across customers.

-
required
object

Customer's mailing address.

-

Responses

Request samples

Content type
application/json
{
  • "name": "John Doe",
  • "email": "john.doe@example.com",
  • "address": {
    }
}

Response samples

Content type
application/json
{
  • "id": "111",
  • "name": "John Doe",
  • "email": "john.doe@example.com",
  • "address": {
    }
}

Products

Get, create, and update products for the e-commerce store.

-

Get a page of products.

query Parameters
category
string

Category name to filter products by.

-
nextToken
string

Accepts a pagination token. The endpoint's responses -return these tokens in the nextToken property.

-
pageSize
integer
Default: 10

Number of products to return per page.

-

Responses

Request samples

curl -v 'http://localhost:8000/products?category=books&pageSize=1'

Response samples

Content type
application/json
{
  • "results": [
    ],
  • "nextToken": "hdW..."
}

Create a product.

Create a product with the specified details.

-
Request Body schema: application/json
required
name
required
string

Name of the product. Must be unique.

-

Internally, the Product collection uses a unique constraint to -ensure name values are unique across products.

-
description
required
string

Description of the product.

-
price
required
number

Price of the product in USD cents.

-

Internally, the Product collection uses a check constraint to -ensure price is a positive number.

-
stock
required
integer

Quantity of the product available in stock.

-

Internally, the Product collection uses a check constraint to -ensure stock is a positive integer.

-
category
required
string

Name of the product's category. Must match an existing category.

-

Internally, this field contains a reference to a Category collection -document.

-

Responses

Request samples

Content type
application/json
{
  • "name": "The Old Man and the Sea",
  • "price": 899,
  • "description": "A book by Ernest Hemingway",
  • "stock": 10,
  • "category": "books"
}

Response samples

Content type
application/json
{
  • "id": "123",
  • "name": "The Old Man and the Sea",
  • "price": 899,
  • "description": "A book by Ernest Hemingway",
  • "stock": 10,
  • "category": {
    }
}

Update a product.

Update the details of a product by its ID.

-
path Parameters
id
required
string

ID of the product to update.

-
Request Body schema: application/json
required
name
required
string

Name of the product. Must be unique.

-

Internally, the Product collection uses a unique constraint to -ensure name values are unique across products.

-
description
required
string

Description of the product.

-
price
required
number

Price of the product in USD cents.

-

Internally, the Product collection uses a check constraint to -ensure price is a positive number.

-
stock
required
integer

Quantity of the product available in stock.

-

Internally, the Product collection uses a check constraint to -ensure stock is a positive integer.

-
category
required
string

Name of the product's category. Must match an existing category.

-

Internally, this field contains a reference to a Category collection -document.

-

Responses

Request samples

Content type
application/json
{
  • "name": "The Old Man and the Sea",
  • "price": 899,
  • "description": "A book by Ernest Hemingway",
  • "stock": 10,
  • "category": "books"
}

Response samples

Content type
application/json
{
  • "id": "123",
  • "name": "The Old Man and the Sea",
  • "price": 899,
  • "description": "A book by Ernest Hemingway",
  • "stock": 10,
  • "category": {
    }
}

Get a page of products by price.

query Parameters
minPrice
number

Minimum price to filter products by.

-
maxPrice
number

Maximum price to filter products by.

-
nextToken
string

Accepts a pagination token. The endpoint's responses -return these tokens in the nextToken property.

-
pageSize
integer
Default: 10

Number of products to return per page.

-

Responses

Request samples

curl -v 'http://localhost:8000/products/by-price?minPrice=199&maxPrice=1099&pageSize=1'

Response samples

Content type
application/json
{
  • "results": [
    ],
  • "nextToken": "hdW..."
}

Orders

Get, create, and update customer orders for the e-commerce store.

-

You can also use these endpoints to create and udpate a customer's cart. -A customer's cart is an order with the cart status. A customer can have -one cart at a time.

-

An order contains zero or more items. An item links a product, with a -quantity, to an order.

-

Get a customer's cart.

Get the details of a customer's cart order.

-
path Parameters
id
required
string

ID of the customer.

-

Responses

Request samples

curl -v http://localhost:8000/customers/111/cart

Response samples

Content type
application/json
{
  • "id": "123",
  • "items": {
    },
  • "total": 0,
  • "status": "cart",
  • "customer": {
    },
  • "createdAt": {
    },
  • "payment": { }
}

Get or create a customer's cart.

Get the details of a customer's cart. If no cart exists, create one with -no items.

-

A customer's cart is an order with the cart status. A customer can -have one cart at a time.

-

To add items to a customer's cart, use the POST /customers/{id}/cart/item endpoint.

-

Internally, the endpoint uses the getOrCreateCart() user-defined -function (UDF) to conditionally get or create the customer's cart.

-
path Parameters
id
required
string

ID of the customer.

-

Responses

Request samples

curl -v -X POST http://localhost:8000/customers/111/cart

Response samples

Content type
application/json
{
  • "id": "123",
  • "items": {
    },
  • "total": 0,
  • "status": "cart",
  • "customer": {
    },
  • "createdAt": {
    },
  • "payment": { }
}

Add an item to a customer's cart.

Add an item to a customer's cart. If the order already contains the -item's product, update the item's quantity.

-

If the customer has no cart, the request create ones.

-

The request returns an item. An item links a product, with a quantity, -to an order. An order contains zero or more items.

-

Internally, the endpoint uses the createOrUpdateCartItem() -user-defined function (UDF) to conditionally update the item's quantity -and create a new cart. The UDF also handles various validations and -error cases for the request.

-
path Parameters
id
required
string

ID of the customer.

-
Request Body schema: application/json
required
productName
required
string

Name of an existing product to add to the order.

-
quantity
required
integer

Quantity of the product to add to the order.

-

Must be a non-negative integer. The quantity must be less than the product's stock.

-

Internally, the OrderItem collection uses a check constraint to -ensure quantity is a positive integer.

-

Responses

Request samples

Content type
application/json
{
  • "productName": "The Old Man and the Sea",
  • "quantity": 1
}

Response samples

Content type
application/json
{
  • "id": 123,
  • "order": {
    },
  • "product": {
    },
  • "quantity": 1
}

Get an order.

Get the details of an order by its ID.

-
path Parameters
id
required
string

ID of the order to fetch.

-

Responses

Request samples

curl -v http://localhost:8000/orders/123

Response samples

Content type
application/json
{
  • "id": "123",
  • "items": {
    },
  • "total": 0,
  • "status": "cart",
  • "customer": {
    },
  • "createdAt": {
    },
  • "payment": { }
}

Update an order.

Update the details of an order by its ID.

-

Changing the order's status to processing runs a checkout on the order.

-

Internally, the endpoint uses the checkout() user-defined function -(UDF) to validate orders during checkout. The UDF:

-
    -
  • Verifies the order is in a processing status.
  • -
  • Ensures the order only adds valid, existing products as items.
  • -
  • Verifies that the order does not reduce any product's stock below zero.
  • -
  • Ensures the order has a non-null payment.
  • -
-
path Parameters
id
required
string

ID of the order to update.

-
Request Body schema: application/json
required
status
string
Enum: "cart" "processing" "shipped" "delivered"

Status of the order.

-

An order's status can only transition as follows:

-

cartprocessingshippeddelivered

-

Internally, the endpoint uses the validateOrderStatusTransition() -user-defined function (UDF) to ensure an order's status change is -allowed.

-
payment
object
Default: {}

Arbitrary object containing payment information.

-

You can only update payment information if the status is cart. -Adding payment information automatically transitions the order's -status to processing.

-

Responses

Request samples

Content type
application/json
{
  • "status": "processing"
}

Response samples

Content type
application/json
{
  • "id": "123",
  • "items": {
    },
  • "total": 0,
  • "status": "cart",
  • "customer": {
    },
  • "createdAt": {
    },
  • "payment": { }
}

Get a customer's orders.

Get the details of a customer's orders using the customer's ID.

-
path Parameters
id
required
string

ID of the customer.

-
query Parameters
nextToken
string

Accepts a pagination token. The endpoint's responses -return these tokens in the nextToken property.

-
pageSize
integer
Default: 10

Number of products to return per page.

-

Responses

Request samples

curl -v 'http://localhost:8000/customers/111/orders?pageSize=1'

Response samples

Content type
application/json
{
  • "results": [
    ],
  • "nextToken": "hdW..."
}
- - - + + + + + + + diff --git a/openapi.yml b/openapi.yml index f9cec18..43e6e70 100644 --- a/openapi.yml +++ b/openapi.yml @@ -2,6 +2,9 @@ openapi: 3.0.3 info: title: Fauna JavaScript sample app version: 1.0.0 + license: + name: Fauna terms + url: "https://fauna.com/terms" description: | HTTP API reference documentation for the [Fauna JavaScript sample app](https://github.com/fauna/js-sample-app). @@ -22,7 +25,7 @@ info: For setup instructions, see the [README](https://github.com/fauna/js-sample-app). servers: - - url: "http://localhost:8000" + - url: / description: Local development server tags: - name: Customers @@ -641,6 +644,9 @@ paths: /customers: post: summary: Create a customer. + operationId: create-customer + security: + - {} tags: - Customers description: Create a customer with the specified details. @@ -728,6 +734,9 @@ paths: "/customers/{id}": get: summary: Get a customer. + operationId: get-customer + security: + - {} tags: - Customers description: Fetch the details of a customer by their ID. @@ -797,6 +806,9 @@ paths: curl -v http://localhost:8000/customers/111 patch: summary: Update a customer. + operationId: update-customer + security: + - {} tags: - Customers description: Update the details of a customer by their ID. @@ -902,6 +914,9 @@ paths: /products: get: summary: Get a page of products. + operationId: get-products + security: + - {} tags: - Products parameters: @@ -989,6 +1004,9 @@ paths: curl -v 'http://localhost:8000/products?category=books&pageSize=1' post: summary: Create a product. + operationId: create-product + security: + - {} tags: - Products description: Create a product with the specified details. @@ -1086,6 +1104,9 @@ paths: "/products/{id}": patch: summary: Update a product. + operationId: update-product + security: + - {} tags: - Products description: Update the details of a product by its ID. @@ -1197,6 +1218,9 @@ paths: /products/by-price: get: summary: Get a page of products by price. + operationId: get-products-by-price + security: + - {} tags: - Products parameters: @@ -1261,6 +1285,9 @@ paths: "/customers/{id}/cart": get: summary: Get a customer's cart. + operationId: get-customer-cart + security: + - {} tags: - Orders description: | @@ -1296,6 +1323,9 @@ paths: curl -v http://localhost:8000/customers/111/cart post: summary: Get or create a customer's cart. + operationId: get-create-customer-cart + security: + - {} tags: - Orders description: | @@ -1342,6 +1372,9 @@ paths: "/customers/{id}/cart/item": post: summary: Add an item to a customer's cart. + operationId: add-cart-item + security: + - {} tags: - Orders description: | @@ -1412,6 +1445,9 @@ paths: "/orders/{id}": get: summary: Get an order. + operationId: get-order + security: + - {} tags: - Orders description: Get the details of an order by its ID. @@ -1429,12 +1465,61 @@ paths: application/json: schema: $ref: "#/components/schemas/OrderResponse" + "400": + description: Bad request + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + examples: + example: + summary: Invalid id + value: + message: Invalid id '!' provided. + "401": + description: Unauthorized + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + examples: + example: + summary: Unauthorized + value: + message: >- + Unauthorized. Set the `FAUNA_SECRET` env var to a valid + Fauna key's secret. + "404": + description: Not found + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + examples: + example: + summary: No order with id + value: + message: No order with id '111' exists. + "500": + description: Internal server error + content: + application/json: + schema: + $ref: "#/components/schemas/ErrorResponse" + examples: + example-1: + summary: Internal server error + value: + message: An unexpected error occurred x-codeSamples: - lang: curl source: |- curl -v http://localhost:8000/orders/123 patch: summary: Update an order. + operationId: update-order + security: + - {} tags: - Orders description: > @@ -1536,6 +1621,9 @@ paths: "/customers/{id}/orders": get: summary: Get a customer's orders. + operationId: get-customer-order + security: + - {} tags: - Orders description: Get the details of a customer's orders using the customer's ID. diff --git a/package.json b/package.json index a02b904..c279d4e 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "build": "tsc", "dev": "nodemon src/index.ts", - "docs": "redocly build-docs openapi.yml --output=docs/index.html", + "lint:openapi": "redocly lint openapi.yml", "start": "npm run build; node build/src/index.js", "test": "jest" },