# Shopping List Quick Start - CLI

This Quick Start uses a familiar concept - a shared Shopping List - to demonstrate how to create and use a Vendia **project**.

This Quick Start uses the Vendia [Command Line Interface (CLI)](https://docs.vendia.com/platform/cli) to create the **project** that will be used in this Quick Start. Alternatively, the [Shopping List Quick Start - Web](https://docs.vendia.com/quickstart/shopping-list-web) can be followed if you prefer a visual over a command-line interface.

## First Things First

Before getting into the mechanics of deploying your **project**, you should first consider what data you want to store and share with others. Let’s consider data that different parties may need to access where each party needs to have a consistent view.

Some of you may recognize this as an inventory management system.

Lots of families use different techniques to share shopping lists. Some use pen-and-paper. Some use spreadsheets. Others use email. Still others use text messages. The point is that different people need to have access to the same set of data and know what changes have been made and by whom. If someone crosses off an item on the list in my house and it’s not in the pantry, I need to know who did it. 😉

## Define Your **Project**

We’ll need to create a _registration_ file that contains information about our **project**:

- Its name
- Where to find the schema
- The **project** participants, each represented as a _Workspace_ in our **project** topology

**NOTE:** You will need to provide your Vendia `userId` when defining your **workspaces**. For this quick start, please use your same `userId` across all **workspaces**.

**ANOTHER NOTE:** [Pick a unique `name` for your **project** that begins with `test-`](https://docs.vendia.com/platform/limits-and-quotas#project-and-workspace-limits) \- by default all **projects** share a common namespace so here is your chance to get creative.

**FINAL NOTE:** Save all of the files mentioned below to the same directory.

### Sample Registration file - save as registration.json

```
{
  "name": "test-shopping-list",
  "schema": "schema.json",
  "nodes": [
    {
      "name": "ParentalUnit1",
      "userId": "me@domain.com",
      "region": "us-west-2",
      "csp": "aws"
    },
    {
      "name": "ParentalUnit2",
      "userId": "me@domain.com",
      "region": "us-west-2",
      "csp": "aws"
    },
    {
      "name": "ChildUnit1",
      "userId": "me@domain.com",
      "region": "us-west-2",
      "csp": "aws"
    },
    {
      "name": "ChildUnit2",
      "userId": "me@domain.com",
      "region": "us-west-2",
      "csp": "aws"
    }
  ]
}
```

### Sample Schema file - save as schema.json

```
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://vendia.com/schemas/demos/shopping-list.json",
  "title": "Shopping List",
  "description": "Store shopping list data",
  "x-vendia-indexes": {},
  "x-vendia-acls": {
    "ShoppingListAcl": {
      "type": "ShoppingList"
    }
  },
  "type": "object",
  "properties": {
    "ShoppingList": {
      "description": "Items on the shopping list",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "item": {
            "description": "What to buy",
            "type": "string"
          },
          "quantity": {
            "description": "How much to buy",
            "type": "string"
          },
          "recommendedLocation": {
            "description": "Where I should buy",
            "type": "string"
          },
          "bought": {
            "description": "Whether it has been bought",
            "type": "boolean"
          },
          "timestampAdded": {
            "description": "When the item was added",
            "type": "string",
            "format": "date-time"
          },
          "timestampPurchased": {
            "description": "When the item was purchased",
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["item"]
      }
    }
  }
}
```

## Create Your **Project**

Now we can use the files required to create a **project**, we can use the Vendia Command Line Interface (CLI) to do so.

### Install the CLI

The `share-cli` can be installed using the NodeJS Node Package Manager (npm).

To install the CLI globally, run the following command:

```
npm install @vendia/share-cli -g
```

**NOTE** You can also install Vendia CLI inside a **project** (instead of globally).

For more information, please visit the [@vendia-cli NPM package page](https://www.npmjs.com/package/@vendia/share-cli) or view the [CLI commands list](https://docs.vendia.com/platform/cli).

### Login and Create a **Project**

Once we have the files saved we are able to deploy our **project** using the `share-cli`.

You must be signed up for Vendia in order to use its APIs. Otherwise, any attempt to invoke the APIs (directly or via the CLI) will result in an “unauthorized user” error message. You will need the user id and password for the following steps.

To log in, run [`share login`](https://docs.vendia.com/platform/cli/commands/login):

```
share login

> Enter your email address

Username: me@domain.com

> Enter your vendia password for me@domain.com

Password: ********************

✔  Logged in as me@domain.com
```

If your login expires, the share CLI will prompt you to log in again during any other command. If you don’t yet have a user account for Vendia you will first [need to sign up](https://share.vendia.net/signup). If you have an account but have forgotten your password, you can [reset your password](https://share.vendia.net/login/reset/).

The `share uni create` command can be used to deploy our **project**.

```
share uni create --config registration.json
```

### Check **Project** Status

The **project** deployment will take approximately 4 minutes. We can check on the status of the **project** by running the `share get` command.

```
% share get --uni test-shopping-list # Adjust **project** name based on the name you specified

Getting test-shopping-list info...

┌─────────────────────┐
│   Uni Information   │
└─────────────────────┘
Uni Name:    test-shopping-list.unis.vendia.net
Uni Status:  PENDING_REGISTRATION
Node Count:  2
Nodes Info:
├─ ⬢ ParentalUnit1
│  ├─ name: ParentalUnit1
│  ├─ status: DEPLOYING
│  └─ resources:
│     ├─ graphqlApi
│     │  ├─ httpsUrl
│     │  ├─ apiKey
│     │  └─ websocketUrl
│     ├─ aws_AsyncIngressQueue
│     │  ├─ url
│     │  └─ name
│     ├─ aws_FileStorage
│     │  ├─ arn
│     │  └─ name
│     ├─ aws_BlockNotifications
│     │  └─ arn
│     ├─ aws_DeadLetterNotifications
│     │  └─ arn
│     └─ aws_Cognito
│        ├─ userPoolId
│        ├─ userPoolClientId
│        └─ identityPoolId
└─ ⬢ ParentalUnit2
   ├─ name: ParentalUnit2
   ├─ status: DEPLOYING
   └─ resources:
      ├─ graphqlApi
      │  ├─ httpsUrl
      │  ├─ apiKey
      │  └─ websocketUrl
      ├─ aws_AsyncIngressQueue
      │  ├─ url
      │  └─ name
      ├─ aws_FileStorage
      │  ├─ arn
      │  └─ name
      ├─ aws_BlockNotifications
      │  └─ arn
      ├─ aws_DeadLetterNotifications
      │  └─ arn
      └─ aws_Cognito
         ├─ userPoolId
         ├─ userPoolClientId
         └─ identityPoolId
To display the schema use the --json flag. Example: "share get test-jgg-shopping-list.unis.vendia.net --json"
```

## Use Your **Project**

Once the **project**’s status transitions to `RUNNING`, we can interact with it to create, read, update, delete, or list data within it.

The remainder of this section works from the Vendia Web Application, specifically its GraphQL explorer view.

If you haven’t done so already, please login to [Vendia](https://share.vendia.net/). When you do, select the **project** created in the previous section and then click the `GraphQL explorer` button to open the GraphQL explorer view.

### Query the Shopping List

Vendia automatically generated a complete [GraphQL interface](https://graphql.org/) automatically when we created our **project**. The [GraphQL Queries](https://graphql.org/learn/queries/) generated allow us to access data in our Shopping List **project** and the [GraphQL Mutations](https://graphql.org/learn/queries/) generated allow us to add or modify data in our Shopping List **project**.

It’s important to remember that each **workspace** has a consistent, shared view of data so any query issued by any **workspace** will return the same value. Any data updates - aka GraphQL mutation - will be applied to all **workspaces** as well.

Let’s run a query run from a **workspace** \- say, **ParentalUnit1** \- to show the Shopping List with our bootstrapped data.

```
query allItems {
  list_ShoppingListItems {
    _ShoppingListItems {
      _id
      item
      quantity
      recommendedLocation
      timestampAdded
      timestampPurchased
    }
  }
}
```

You should see a result similar to this one:

### Add Items to the Shopping List

Our **project** started off with some existing data but let’s add some more.

If **ParentalUnit2** wants to have someone pick up two pints of Ben and Jerry’s Chubby Hubby ice cream then a mutation will need to be run from the **ParentalUnit2** GraphQL Explorer.

```
mutation addIceCream {
  add_ShoppingList(
    input: {
      item: "Ben and Jerry Chubby Hubby"
      bought: false
      quantity: "2 pints"
      recommendedLocation: "Corner Store"
      timestampAdded: "2021-11-11T17:15:32Z"
    }
    syncMode: ASYNC
  ) {
    transaction {
      _id
    }
  }
}
```

A subsequent query run from any **workspace** \- say, ParentalUnit1 - will show the new item in the Shopping List.

```
query allItems {
  listShoppingLists {
    ShoppingLists {
      bought
      _id
      item
      quantity
      recommendedLocation
      timestampAdded
      timestampPurchased
    }
  }
}
```

Let’s go ahead and add some more items. In my household, **ParentalUnit1** manages most of the shopping list. We can run the following mutations from the **ParentalUnit1** GraphQL Explorer.

```
mutation addMilk {
  add_ShoppingList(
    input: {
      item: "Milk"
      bought: false
      quantity: "1 gallon"
      recommendedLocation: "Awesome Mart"
      timestampAdded: "2020-11-11T09:00:00Z"
    }
    syncMode: ASYNC
  ) {
    transaction {
      _id
    }
  }
}
```

```
mutation addEggs {
  add_ShoppingList(
    input: {
      item: "Eggs"
      bought: false
      quantity: "1 dozen"
      recommendedLocation: "Rural Farm Market"
      timestampAdded: "2021-11-11T13:40:00Z"
    }
    syncMode: ASYNC
  ) {
    transaction {
      _id
    }
  }
}
```

### Query the Shopping List Again

#### Unfiltered Query

We have the ability to retrieve all of the items in our shopping list. This can be done with the following query.

```
query allItems {
  list_ShoppingListItems {
    _ShoppingListItems {
      _id
      item
      quantity
      recommendedLocation
      timestampAdded
      timestampPurchased
    }
  }
}
```

Screenshot of ParentalUnit1 querying the Shopping List after Ice Cream, Milk, and Eggs were added

**NOTE**: It is possible to have multiple GraphQL queries in the GraphQL Explorer.

> Be sure to select the _allItems_ query when clicking the Play (Execute Query) button.

#### Filtered Query

We have the ability to narrow down the results returned from our Shopping List queries. As a practical matter, we may only be concerned with items that should be bought at a specific store. We can run the following query to narrow down items that have a `recommendedLocation` equal to `Awesome Mart` where `bought` is equal to `false`.

```
query awesomeMartQuery {
  listShoppingLists(
    filter: {
      recommendedLocation: { eq: "Awesome Mart" }
      bought: { eq: false }
    }
  ) {
    ShoppingLists {
      bought
      _id
      item
      quantity
      recommendedLocation
      timestampAdded
      timestampPurchased
    }
  }
}
```

### Update the Shopping List

If **ParentalUnit2** happens to be at `Awesome Mart` then they might purchase 1 Gallon of Milk. The following query, specifically a _mutation_, can be run to update the shopping list to reflect that Milk has been bought.

**NOTE** The `id` value in the mutation below will be different for you. Please reference the `id` returned from the `awesomeMartQuery` query.

```
mutation boughtMilk {
  update_ShoppingList(
    id: "017d1002-1c8c-6e64-3504-f81bf919573e"
    input: { bought: true, timestampPurchased: "2021-11-11T10:00:00Z" }
  ) {
    transaction {
      _id
    }
  }
}
```

Let’s confirm that the Shopping List reflects that Milk has been bought. The `bought` value should be updated to `true`.

```
query awesomeMartQuery {
  list_ShoppingListItems(
    filter: { recommendedLocation: { eq: "Awesome Mart" } }
  ) {
    _ShoppingListItems {
      bought
      _id
      item
      quantity
      recommendedLocation
      timestampAdded
      timestampPurchased
    }
  }
}
```

### Examine Shopping List Change History

One very important characteristic of Vendia is the ability to present all changes to all data to all **workspaces** in a **project**. We can see how data in our **project** evolves over time. To look at the changes to our Shopping List, we can run the following query.

```
query shoppingListChanges {
  listVendia_BlockItems {
    Vendia_BlockItems {
      blockId
      commitTime
      transactions {
        mutations
        _owner
      }
    }
  }
}
```

Result of shopping List Changes GraphQL Query

```
{
  "data": {
    "listVendia_BlockItems": {
      "Vendia_BlockItems": [
        {
          "blockId": "000000000000001",
          "commitTime": "2021-11-09T22:25:55.790334+00:00",
          "transactions": [
            {
              "mutations": [
                "addSelf_ShoppingList(id:\"017d06c6-92c0-efbd-ad56-7b47914d288e\", input: {item: \"Cheese\", quantity: \"2 lb\", recommendedLocation: \"Cheesy Charlies\", bought: false, timestampAdded: \"2020-12-05T14:23:32Z\"}){error}"
              ],
              "_owner": "ParentalUnit1"
            },
            {
              "mutations": [
                "putVendia_UniInfo(input: {name: \"test-brian-shopping-list.unis.vendia.net\", sku: \"SHARE\", schema: \"{\\\"$schema\\\":\\\"http://json-schema.org/draft-07/schema#\\\",\\\"$id\\\":\\\"http://vendia.com/schemas/demos/shopping-list.json\\\",\\\"title\\\":\\\"Shopping List\\\",\\\"description\\\":\\\"Store shopping list data\\\",\\\"type\\\":\\\"object\\\",\\\"properties\\\":{\\\"ShoppingList\\\":{\\\"description\\\":\\\"Items on the shopping list\\\",\\\"type\\\":\\\"array\\\",\\\"items\\\":{\\\"type\\\":\\\"object\\\",\\\"properties\\\":{\\\"item\\\":{\\\"description\\\":\\\"What to buy\\\",\\\"type\\\":\\\"string\\\"},\\\"quantity\\\":{\\\"description\\\":\\\"How much to buy\\\",\\\"type\\\":\\\"string\\\"},\\\"recommendedLocation\\\":{\\\"description\\\":\\\"Where I should buy\\\",\\\"type\\\":\\\"string\\\"},\\\"bought\\\":{\\\"description\\\":\\\"Whether it has been bought\\\",\\\"type\\\":\\\"boolean\\\"},\\\"timestampAdded\\\":{\\\"description\\\":\\\"When the item was added\\\",\\\"type\\\":\\\"string\\\",\\\"format\\\":\\\"date-time\\\"},\\\"timestampPurchased\\\":{\\\"description\\\":\\\"When the item was purchased\\\",\\\"type\\\":\\\"string\\\",\\\"format\\\":\\\"date-time\\\"}},\\\"required\\\":[\\\"item\\\"]}}}}\", schemaNamespace: \"Self\", status: \"RUNNING\", createdTime: \"2021-11-09T22:16:56.130845+00:00\", updatedTime: \"2021-11-09T22:25:55.790334+00:00\", nodes: [{name: \"ParentalUnit1\", userId: \"2674ecfd-f65a-48c9-99bd-fe0115a00ab6\", userEmail: \"brian+demo@vendia.net\", status: \"RUNNING\", region: \"us-west-2\", vendiaAccount: {csp: \"AWS\", accountId: \"943506818770\", org: \"332134949057\"}}, {name: \"ParentalUnit2\", userId: \"2674ecfd-f65a-48c9-99bd-fe0115a00ab6\", userEmail: \"brian+demo@vendia.net\", status: \"RUNNING\", region: \"us-west-2\", vendiaAccount: {csp: \"AWS\", accountId: \"532889100462\", org: \"332134949057\"}}}]}) {error}"
              ],
              "_owner": "ParentalUnit1"
            }
          ]
        },
        {
          "blockId": "000000000000002",
          "commitTime": "2021-11-11T16:22:05.552619+00:00",
          "transactions": [
            {
              "mutations": [
                "addSelf_ShoppingList(id:\"017d0fce-4808-9026-ffd4-db5b64ec121b\",input: {bought: false, item: \"Ben and Jerry Chubby Hubby\", quantity: \"2 pints\", recommendedLocation: \"Corner Store\", timestampAdded: \"2021-11-11T17:15:32Z\"}){error}"
              ],
              "_owner": "ParentalUnit2"
            }
          ]
        },
        {
          "blockId": "000000000000003",
          "commitTime": "2021-11-11T17:18:42.959053+00:00",
          "transactions": [
            {
              "mutations": [
                "addSelf_ShoppingList(id:\"017d1002-1c8c-6e64-3504-f81bf919573e\",input: {bought: false, item: \"Milk\", quantity: \"1 gallon\", recommendedLocation: \"Awesome Mart\", timestampAdded: \"2020-11-11T09:00:00Z\"}){error}"
              ],
              "_owner": "ParentalUnit1"
            }
          ]
        },
        {
          "blockId": "000000000000004",
          "commitTime": "2021-11-11T17:23:52.472582+00:00",
          "transactions": [
            {
              "mutations": [
                "addSelf_ShoppingList(id:\"017d1006-e604-14bc-d16e-38b9b8a62c3c\",input: {bought: false, item: \"Eggs\", quantity: \"1 dozen\", recommendedLocation: \"Rural Farm Market\", timestampAdded: \"2021-11-11T13:40:00Z\"}){error}"
              ],
              "_owner": "ParentalUnit1"
            }
          ]
        },
        {
          "blockId": "000000000000005",
          "commitTime": "2021-11-11T17:48:42.473748+00:00",
          "transactions": [
            {
              "mutations": [
                "updateSelf_ShoppingList(id:\"017d1002-1c8c-6e64-3504-f81bf919573e\",input: {bought: true, timestampPurchased: \"2021-11-11T10:00:00Z\"}){error}"
              ],
              "_owner": "ParentalUnit2"
            }
          ]
        }
      ]
    }
  }
}
```

Take note that we have the ability to see the _Mutation_ that was run to update the Shopping List, the _Owner_ or **workspace** who introduced the change, and when the change occurred. This demonstrates the value and utility of Vendia’s serverless distributed ledger backing our Shopping List.

## What’s Next

This quick start illustrated how to define Vendia **projects** and how to query and update data in the **project**. We used the built-in GraphQL Explorer provided by each **workspace**.

Though our Shopping List example, we showed how each **workspace** in the Shopping List **project** has a consistent view of the data. When we query for all items, or a subset of items, any party will see the same data. We also showed that any changes to the underlying data - the GraphQL mutation that was run and the party that ran it - is visible to all **workspaces**.

Please keep in mind we are not constrained to simply using the GraphQL explorer. Vendia provides other mechanisms for getting data into and out of **projects**. Please refer to our documentation on [Integrating Vendia Projects with Other Cloud-based Services](https://docs.vendia.com/platform/integrations).
