Skip to main content

Getting Started

Start with Docker

Mongo installation:

docker run -d --name mongo6 -p 27017:27017 mongo:6 mongod --replSet rs
# 0fb24fd1422e45efa2d37ea...

Initialize the replicaSet1:

mongo mongodb://localhost:27017/datastore \
--eval 'rs.initiate({"_id":"rs","members":[{"_id":0,"host":"localhost:27017"}]})'
# { "ok" : 1 }

Datastore deployment with administration API up as well as the backoffice (remove this flags in production):

docker run \
-d --name datastore \
--network host \
-e PORT=3001 -e NODE_ENV=development \
-e FEATURE_API_TEMPLATES=true -e FEATURE_API_ADMIN=true \
getanthill/datastore:latest
# 0fb24fd1422e45efa2d37ea...

Check the heartbeat:

curl http://localhost:3001/heartbeat
# {"state":"up"}

The OpenAPI Documentation is available here:

http://localhost:3001/api/api-docs

and can be rendered with the Swagger UI with the following link2:

https://petstore.swagger.io/?url=http://localhost:3001/api/api-docs

Creating your first model

Create a simple Event-Source model with:

We are using jq extensively hereafter. Please install it and support it ❤️!

You can view examples of models with the following command:

curl http://localhost:3001/api/templates/examples/users.json | jq
# {
# "db": "datastore",
# "name": "users",
# "correlation_field": "user_id",
# "schema": {
# "model": {
# "additionalProperties": true,
# "properties": {
# "firstname": {
# "type": "string"
# }
# }
# },
# "events": {
# "CREATED": {
# "0_0_0": {
# "properties": {
# "firstname": {
# "type": "string"
# }
# }
# }
# }
# }
# }
# }

You can then pipe the files available as examples to the model creation request:

curl http://localhost:3001/api/templates/examples/users.json | \
curl -X POST 'http://localhost:3001/api/admin' \
-H 'Authorization: token' \
-H 'Content-Type: application/json' \
-d @- | jq
# {
# "db": "datastore",
# "name": "users",
# "correlation_field": "user_id",
# "created_at": "2020-11-28T17:48:40.236Z",
# "updated_at": "2020-11-28T17:48:40.236Z",
# "version": 0,
# "model_id": "5fc28d781f139c00120935aa",
# ...
# }

Great, let's check that everything is right now and that we are able to create new users!

The following command will check that the datastore correctly took into account your new model

curl -X GET 'http://localhost:3001/api/admin' \
-H 'Authorization: token' \
-H 'Content-Type: application/json' | \
jq '{name: .users.name}'
# {
# "name": "users"
# }

Requesting the API

Let's start creating a user Alice:

curl -X POST 'http://localhost:3001/api/users' \
-H 'Authorization: token' \
-H 'Content-Type: application/json' \
-d '{
"firstname": "Alice"
}' | jq
# {
# "created_at": "2021-10-28T17:57:45.812Z",
# "firstname": "Alice",
# "updated_at": "2021-10-28T17:57:45.812Z",
# "version": 0,
# "user_id": "617ae499f4b53601ade4a164"
# }

You now have an entity called Alice with version=0!

You can retrieve the exact same document with the following request:

curl -X GET 'http://localhost:3001/api/users/617ae499f4b53601ade4a164' \
-H 'Authorization: token' \
-H 'Content-Type: application/json' | jq
# {
# "created_at": "2021-10-28T17:57:45.812Z",
# "firstname": "Alice",
# "updated_at": "2021-10-28T17:57:45.812Z",
# "version": 0,
# "user_id": "617ae499f4b53601ade4a164"
# }
caution

Keep in mind that the user_id 617ae499f4b53601ade4a164 value will change during your own execution!

We can also try to find Alice with:

curl -X GET 'http://localhost:3001/api/users?firstname=Alice' \
-H 'Authorization: token' \
-H 'Content-Type: application/json' | jq
# [
# {
# "created_at": "2021-10-28T17:57:45.812Z",
# "firstname": "Alice",
# "updated_at": "2021-10-28T17:57:45.812Z",
# "version": 0,
# "user_id": "617ae499f4b53601ade4a164"
# }
# ]

Changing the firstname of Alice to Alizz would be performed with another POST request like so:

curl -X POST 'http://localhost:3001/api/users/617ae499f4b53601ade4a164' \
-H 'Authorization: token' \
-H 'Content-Type: application/json' \
-d '{
"firstname": "Alizz"
}' | jq
# {
# "created_at": "2021-10-28T17:57:45.812Z",
# "firstname": "Alizz",
# "updated_at": "2021-10-28T18:04:11.449Z",
# "version": 1,
# "user_id": "617ae499f4b53601ade4a164"
# }

Did you notice the change on the value of version? This is now that you will discover the power of Event-Sourcing!

Let's find the events associated to Alice:

curl -X GET 'http://localhost:3001/api/users/617ae499f4b53601ade4a164/events' \
-H 'Authorization: token' \
-H 'Content-Type: application/json' | jq
# [
# {
# "_id": "617ae499f4b53601ade4a165",
# "created_at": "2021-10-28T17:57:45.812Z",
# "type": "CREATED",
# "v": "0_0_0",
# "firstname": "Alice",
# "version": 0,
# "user_id": "617ae499f4b53601ade4a164"
# },
# {
# "_id": "617ae61bf4b53601ade4a166",
# "created_at": "2021-10-28T18:04:11.449Z",
# "type": "UPDATED",
# "v": "0_0_0",
# "firstname": "Alizz",
# "version": 1,
# "user_id": "617ae499f4b53601ade4a164"
# }
# ]

We see that 2 events have been stored in the database: 1 for the creation, 1 for the firstname update.

Let's say that we changed our mind and we want now to restore Alice instead of Alizz. We can do that with the restoration route:

curl -X POST 'http://localhost:3001/api/users/617ae499f4b53601ade4a164/0/restore' \
-H 'Authorization: token' \
-H 'Content-Type: application/json' | jq
# {
# "created_at": "2021-10-28T17:57:45.812Z",
# "firstname": "Alice",
# "updated_at": "2021-10-28T18:11:37.325Z",
# "version": 2,
# "user_id": "617ae499f4b53601ade4a164"
# }

We are now at version=2. And the firstname has been restored to Alice! And you can do that every model you are managing with the datastore.

Clean

Now that your tried with success the datastore, you can clean everything with the following commmands:

docker stop datastore mongo6
docker rm datastore mongo6
docker rmi getanthill/datastore:latest mongo:6

  1. Required for streaming but not mandatory if you do not use that feature
  2. Might require the installation and activation of the chrome extension Allow CORS: Access-Control-Allow-Origin