Tutorial 1 - Setting up your local environment and initial app
In this tutorial, you will set up your local simulator environment using CLI tools to simulate your first blueprint running in its own Datastore service, and configure the JavaScript Software Development Kit (JS SDK) to work with this blueprint.
You will also examine the initial blueprint files and JavaScript files (for the event application), which are provided for you from the tutorial source file package.
This tutorial takes around 30-40 minutes to complete.
Install the CLI tools
Set up the Datastore command line interface (CLI) tools locally on your computer to run the local simulator, which allows you to develop and test your blueprint and event management application locally.
Read the DXP CLI Get Started section to learn how to set up your system locally.
Prepare your local workspace and obtain the tutorial source files
Before starting the tutorials, set up your local working directory for your blueprint and application files, and download and extract the tutorial source file package.
-
Run the following commands to set up your tutorial’s workspace and to create an empty blueprint ready for simulation:
-
Create and enter the
datastore-tutorial
directory:$ mkdir datastore-tutorial $ cd datastore-tutorial
-
Obtain the tutorial source files and extract them:
$ curl https://blueprints.datastore.squiz.cloud/tutorialv2.tar.gz --output tutorial.tar.gz $ tar -xvf tutorial.tar.gz $ rm tutorial.tar.gz
-
Create and enter the working directory for your event application (
event-app
):$ mkdir event-app $ cd event-app
-
Within the
event-app
directory, create the initial file structures for your event application’s blueprint:$ mkdir api $ touch api/api.yaml
-
-
Ensure your local
datastore-tutorial
directory and file structure matches this structure:datastore-tutorial |_ event-app |_ api |_ api.yaml |_ tutorial |_ ... contains all downloaded and extracted tutorial source files
Add your initial blueprint to your local simulator
Use the newly installed Datastore CLI tool to start running your local Datastore simulator and add your initial blueprint file to it.
-
Ensure you are still in the
event-app
directory. -
Run the following command to simulate the empty (
api.yaml
) initial blueprint that was created when you prepared your local workspace:$ dxp-next datastore simulator add --blueprint api/api.yaml
which if run successfully, should provide a result like this:
✔ Done! Use these details for local querying: URL: http://0.0.0.0:7001/aBCDEFGh JWT URL: http://0.0.0.0:7001/__JWT/issueToken ...
The command will take a few moments to run while the simulation environment is prepared. |
Configure the local JS SDK to use your simulated blueprint
This tutorial uses a local JS SDK which provides query and filter methods that interact with your blueprint’s API in the Datastore simulator. These methods prevent the need for developers to write bespoke code to add, find, update and delete document data and collections within their Datastore service.
The settings to configure the interactions between the JS SDK and your Datastore simulator are defined in a settings
object.
This configuration is often defined in your app’s main.js file.
However, since the main.js file in this set of tutorials is overwritten during most of the subsequent tutorials, the settings object is defined in a separate file, to prevent you having to reconfigure its Datastore service URL value each time.
|
To define the settings
object:
-
Create a
settings.js
file in theevent-app
directory, with the following source code:const settings = { serviceURL: '<replace-with-your-datastore-service-url>' };
-
Replace the
serviceURL
value with the URL value provided in the CLI output when you added the blueprint above.You can always retrieve your Datastore service’s URL value with the command:
$ dxp-next datastore simulator list
-
Save your updated
settings.js
file.
Copy the 'tutorial 1' files over to your event-app
directory and test the app
Now copy the initial stage of your app’s functionality from the source tutorial repository over to your event-app
directory.
-
From the
event-app
directory, copy the content of thestep1
directory to theevent-app
directory:$ cp -r ../tutorial/step1/* .
-
Test that the initial application loads by opening the
index.html
file in theevent-app
directory, directly in a web browser. This web application is designed to run without a web server.-
Click the Create an event button to begin creating an event.
-
Specify an event’s Name and Description (in the Create an event dialog box).
-
Click Create event to save the event.
-
-
If you find that creating an event does not work, or you receive an "Internal server error" upon opening the To resolve these issues, try upgrading your local Datastore simulation environment first, and then re-try the 'test' step above. |
Examine how the API endpoints of your blueprint are defined
In this section, you will examine the file content that was copied over from the previous step.
This will provide you with an insight and foundation into how your blueprint’s API specifications and data models are defined and constructed.
In subsequent tutorials, you will add to these definitions yourself. |
Examine the API specification (api.yaml
) file
As explained in detail in https://docs.squiz.net/datastore/latest/features/data-organization-within-collections-and-documents.html, the api.yaml
file in the api/
directory defines the initial API endpoints for:
-
A collection named
events
(accessible through the/events
endpoint), which defines GET and POST requests. -
Individual event documents (contained within the
events
collection), whose names are dynamic IDs assigned by Datastore (accessible through the/events/{eventid}
endpoint), which defines an initial GET request, where the name of the event document is the parameter itself.
In the event-app/api/
directory, open the api.yaml
file to examine its content:
paths:
/events:
get: (1)
description: Gets all events for a user
...
post: (2)
description: Adds a new event
...
/events/{eventid}:
parameters: (3)
- in: path
name: eventid
description: ID of an event
required: true
schema:
type: string
get: (4)
description: Get an event by ID
...
1 | Definition for the GET request for the /events collection endpoint.Note: If a GET request is defined on a collection endpoint (like this), then the collection’s document endpoint (below) must also define a GET request. |
2 | Definition for the POST request for the /events collection endpoint. |
3 | Definition for the characteristics of the /events/{eventid} document endpoint’s parameter value, where the parameter value is the {eventid} name itself.Note: Although the app will not yet utilize this endpoint until Tutorial 3, this definition in the API specification (YAML) file is required whenever a GET request is defined on the parent collection endpoint (i.e. /events above). |
4 | Definition for the GET request for the /events/{eventid} document endpoint.Note: As explained above, a GET request must be defined on this document endpoint when a GET request is defined on its parent collection endpoint. |
This simple API structure allows for URLs like /events
and /events/0cad4697-8422-47c0-9d4b-5f16d7f5baf3
(as an example) to represent the main collection and individual events within it, respectively.
Examine the JSON schema (data model) files
The JSON schema files (in the schemas/
directory) define the data that each endpoint accepts.
Examine the event.json
file
The event.json
file defines the data that the /events/{eventid}
endpoint sends and/or receives.
This is explained in more detail below.
In the event-app/api/schemas/
directory, open the event.json
file to examine its content:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"name": { (1)
"description": "The name of the event.",
"type": "string",
"example": "Music Festival"
},
"description": { (2)
"description": "The name of the event.",
"type": "string",
"example": "A festival of music, circus and magic."
}
}
}
1 | Definition for the /events/{eventid} endpoint’s name string property. |
2 | Definition for the same endpoint’s description string property. |
Other than strings, properties can also be integers, numbers, booleans, dates/times and nulls. A property could also be an array containing multiple values of any of these supported types. |
Examine the events.json
file
The events.json
file defines the data that the /events
endpoint receives.
In the event-app/api/schemas/
directory, open the events.json
file to examine its content:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {
"$ref": "./event.json" (1)
}
}
1 | Definition for the /events endpoint’s array property, which is an array of objects defined by the event.json file in the same directory.
This array represents a collection of documents, where each document’s properties are defined by the event.json file.
This type of definition is required if a method’s request to a document (i.e. the event via the /events/{eventid} endpoint) within a collection (i.e. events ) requires event properties to be either passed in its payload, or provided in the response from Datastore. |
Examine the remainder of the api.yaml
file
Examining the remainder of the api.yaml
file shows how the properties defined in the event.json
and events.json
files (above) relate to the API endpoint definitions.
paths:
/events:
get:
description: Gets all events for a user
x-datastore-acl: public
responses: (1)
'200':
description: Array of events
content:
application/json:
schema:
$ref: './schemas/events.json'
post:
description: Adds a new event
x-datastore-acl: public
responses: (2)
'201':
description: The event info is returned
content:
application/json:
schema:
$ref: './schemas/event.json'
requestBody: (2)
content:
application/json:
schema:
$ref: './schemas/event.json'
/events/{eventid}:
parameters:
- in: path
name: eventid
description: ID of an event
required: true
schema:
type: string
get:
description: Get an event by ID
x-datastore-acl: public
responses: (3)
'200':
description: The event info is returned
content:
application/json:
schema:
$ref: './schemas/event.json'
1 | The GET response from the /events endpoint returns properties defined by the events.json object.
This response retrieves a collection (i.e. an array) of individual event documents, whose properties are defined by the event.json file. |
2 | The POST request to (and response from) the /events endpoint returns properties defined by the event.json object.
The request creates a new event document, whose properties are defined by the event.json object.
The response is also an event document, whose properties are defined by event.json . |
3 | The GET response from the /events/{eventid} endpoint returns properties defined by the event.json object.
This response retrieves an event document, whose name is {eventid} , and whose properties are defined by the event.json object. |
Examine how the JS SDK is used
To ensure your web application uses the local JS SDK simulator, incorporate its library towards the end of your web application’s HTML file.
The local JS SDK and Datastore configuration in the index.html
file
In the event-app
directory, open the index.html
file and scroll towards the end of the file.
The following code snippet shows how the local JS SDK and Datastore are configured in this file.
<html>
....
<body>
....
<!-- Datastore JS -->
<script src="./src/datastoresim.js"></script> (1)
<script src="./settings.js"></script> (2)
<script>
// Datastore JS SDK object.
const datastore = new Datastore(settings); (3)
</script>
<script src="./main.js"></script>
</body>
</html>
1 | Incorporates the Datastore JS SDK simulator class into the web application. |
2 | References the settings.js file you set above to configure Datastore within your app.
Note that configuring Datastore details for the JS SDK would normally be a part of the main.js file (and optionally instantiated there), as depicted in the code snippet below.
However, since this tutorial uses the cp command to re-write the existing main.js file with more code and functionality, the definition for the settings constant has been moved into a separate settings.js file to avoid you having to re-specify the Datastore URL in main.js each time. |
3 | Instantiates the Datastore object. |
main.js
itselfconst settings = {
serviceURL: '<Your URL here>'
};
const datastore = new Datastore(settings);
Examine the getEvents
function in the main.js
file
In the event-app
directory, open the main.js
file and examine the const getEvents …
function definition towards the top of the file.
The following code snippet shows the JS SDK call to retrieve a list of events (i.e. from a collection).
/**
* Gets all events for My Event Manager
*/
const getEvents = () => {
datastore.collection('events').get().then( (1)
(events) => {
if (events.length === 0) {
...
// Code to handle what happens when there are no events.
...
} else {
events.forEach((event) => {
printEvent(event); (2)
});
}
}
);
};
1 | The JS SDK call to get a list of events. The datastore.collection() method prepares a collection request on the top-level collection (i.e. events ) defined in the API specification above.The get() method is then called on this collection() to send a GET request (on the prepared collection request) to retrieve the events collection’s array of individual event document objects.This method uses the blueprint’s get definition within /events , which is also defined in the API specification above, to retrieve the requested collection of event documents from Datastore.Then, if all goes well … |
2 | Outputs a list of each event document in the events collection. |
Examine the addEvent
function
Further down in the main.js
file, the following code snippet shows the JS SDK call to add an event (i.e. document).
/**
* Adds a new event to My Event Manager
*/
const addEvent = () => {
const data = getData('#createEvent'); (1)
datastore.collection('events').add(data).then((event) => { (2)
printEvent(event); (3)
...
});
};
1 | Contains JavaScript code to retrieve the properties' values (from the app) for the newly created event, temporarily held by the data constant. |
2 | The JS SDK call to add the event to the events collection.The datastore.collection() method prepares a collection request on the top-level collection (i.e. events ) defined in the API specification above.The add() method is then called on this collection() to send a POST request (on the prepared collection request) to add the new event properties' values in the data constant, as a new document of this events collection.This method uses the API’s post definition within /events , which is also defined in the API specification above.Then, if all goes well … |
3 | Outputs the event data that was added to the events collection. |
Now that you understand the fundamentals of how to define API endpoints and work with the JS SDK to use these API endpoints, you can now extend the functionality of your events management app to handle more structured data.