Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace CURL inputs with JS code samples #2138

Merged
merged 17 commits into from
Nov 23, 2021
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 98 additions & 62 deletions docs/api/client/http-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,65 @@ description: ReSolve provides a standard HTTP API that allows you to send aggreg

EugeniyBurmistrov marked this conversation as resolved.
Show resolved Hide resolved
ReSolve provides a standard HTTP API that allows you to send aggregate commands, and query Read and View Models.
EugeniyBurmistrov marked this conversation as resolved.
Show resolved Hide resolved

## Command API

You can send a command from the client side as a POST request to the following URL:

```
http://{host}:{port}/api/commands
```

The request body should have the `application/json` content type and contain the command's JSON representation.

```
{
"aggregateName": aggregateName,
"type": commandType,
"aggregateId": aggregateID,
"payload": {
"param1": value1,
"param2": value2,
...
"paramN": valueN
}
}
```

| Name | Type | Description |
| ----------------- | ------ | ------------------------------------------------------ |
| **aggregateId** | string | The ID of an aggregate that should handle the command. |
| **aggregateName** | string | The aggregate's name as defined in **config.app.js**. |
| **commandType** | string | The command type that the aggregate can handle. |
| **payload** | object | Parameters the command accepts. |

#### Example

```js
const apiCommandsUrl = '/api/commands'

const sendCommand = async ({
aggregateName,
aggregateId,
type,
payload,
jwt,
}) => {
await fetch(apiCommandsUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${jwt}`,
},
body: JSON.stringify({
aggregateName,
aggregateId,
type,
payload,
}),
})
}
```

## Read Model API

To query a Read Model from the client side, send a POST request to the following URL:
Expand All @@ -14,12 +73,12 @@ To query a Read Model from the client side, send a POST request to the following
http://{host}:{port}/api/query/{readModel}/{resolver}
```

##### URL Parameters:
#### URL Parameters:

| Name | Description |
| ------------- | ----------------------------------------------------------------------- |
| **readModel** | The Read Model name as defined in the application's configuration file. |
| **resolver** | The name of a [resolver defined in the Read Model](#resolvers) |
| **resolver** | The name of a [resolver defined in the Read Model](#resolvers). |

The request body should have the `application/json` content type and the following structure:

Expand All @@ -34,76 +93,53 @@ The request body should have the `application/json` content type and the followi

The object contains parameters that the resolver accepts.

## View Model API

To query a View Model from the client side, send a GET request to the following URL:
#### Example

```
http://{host}:{port}/api/query/{viewModel}/{aggregateIds}
```

##### URL Parameters

| Name | Description |
| ------------ | --------------------------------------------------------------------------------------------------------- |
| viewModel | The View Model name as defined in the application's configuration file |
| aggregateIds | The comma-separated list of Aggregate IDs to include in the View Model. Use `*` to include all Aggregates |

##### Example

Use the following command to get the [shopping-list](https://github.com/reimagined/resolve/tree/master/examples/js/shopping-list) example application's state:

```sh
curl -g -X GET "http://localhost:3000/api/query/Default/shoppingLists"
```js
const apiQueryUrl = '/api/query'

const queryReadModel = async (readModelName, resolver, parameters, jwt) => {
const requestUrl = `${apiQueryUrl}/${readModelName}/${resolver}`
const res = await fetch(requestUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${jwt}`,
},
body: JSON.stringify(parameters),
})
return await res.json()
}
```

## Command API

You can send a command from the client side as a POST request to the following URL:

```
http://{host}:{port}/api/commands
```
## View Model API

The request body should have the `application/json` content type and contain the command's JSON representation.
To query a View Model from the client side, send a GET request to the following URL:

```
{
"aggregateName": aggregateName,
"type": commandType,
"aggregateId": aggregateID,
"payload": {
"param1": value1,
"param2": value2,
...
"paramN": valueN
}
}
http://{host}:{port}/api/query/{viewModel}/{aggregateIds}
```

| Name | Type | Description |
| ----------------- | ------ | ----------------------------------------------------- |
| **aggregateId** | string | The ID of an aggregate that should handle the command |
| **aggregateName** | string | The aggregate's name as defined in **config.app.js** |
| **commandType** | string | The command type that the aggregate can handle |
| **payload** | object | Parameters the command accepts |
#### URL Parameters

##### Example
| Name | Description |
| ------------ | ---------------------------------------------------------------------------------------------------------- |
| viewModel | The View Model name as defined in the application's configuration file. |
| aggregateIds | The comma-separated list of Aggregate IDs to include in the View Model. Use `*` to include all Aggregates. |

Use the following command to add an item to the **shopping-list** example:
#### Example

```sh
$ curl -X POST "http://localhost:3000/api/commands"
--header "Content-Type: application/json" \
--data '
{
"aggregateName":"Todo",
"type":"createItem",
"aggregateId":"root-id",
"payload": {
"id":`date +%s`,
"text":"Learn reSolve API"
}
```js
const apiQueryUrl = '/api/query'

const queryViewModel = async (viewModelName, aggregateIds, jwt) => {
const requestUrl = `${apiQueryUrl}/${viewModelName}/${aggregateIds.join(',')}`
const res = await fetch(requestUrl, {
method: 'GET',
headers: {
Authorization: `Bearer ${jwt}`,
},
})
return await res.json()
}
'
```
Binary file removed docs/assets/curl/list1-items.png
Binary file not shown.
31 changes: 1 addition & 30 deletions docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,39 +24,10 @@ View Models are a Redux-specific extension to these mechanisms. View models are
**A**: Implement a [custom Read Model](read-side.md#custom-read-models). Custom Read Models allow you to use custom logic to communicate with a Read Model store.

EugeniyBurmistrov marked this conversation as resolved.
Show resolved Hide resolved
**Q**: How to send an aggregate command?<br/>
EugeniyBurmistrov marked this conversation as resolved.
Show resolved Hide resolved
**A**: To send a command from a client browser, use the [standard HTTP API](frontend.md#http-api): <br/>

```
$ curl -X POST "http://localhost:3000/api/commands"
--header "Content-Type: application/json" \
--data '
{
"aggregateName":"Todo",
"type":"createItem",
"aggregateId":"root-id",
"payload": {
"id":`date +%s`,
"text":"Learn reSolve API"
}
}
```
**A**: To send a command from a client browser, use the reSolve HTTP API or one of the available client libraries. Refer to the [Frontend](frontend.md) article for more information.

On the server side, you can [send a command](api/saga.md#executecommand) from an API Handler or Saga:

<!-- prettier-ignore-start -->

[mdis]:# (../tests/saga-sample/saga.js#execute)
```js
await sideEffects.executeCommand({
aggregateName: 'User',
aggregateId: event.aggregateId,
type: 'requestConfirmUser',
payload: event.payload,
})
```

<!-- prettier-ignore-end -->

**Q**: How to perform validation to ensure input values are unique?<br/>
EugeniyBurmistrov marked this conversation as resolved.
Show resolved Hide resolved
**A**: In a distributed application, it is not possible to perform reliable checks. You should detect value duplicates in a Read Model or Saga projection code and mark duplicated values as incorrect.

EugeniyBurmistrov marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Loading