owned this note
owned this note
Published
Linked with GitHub
[Back to LOC CLI Guidebook](https://hackmd.io/4LIsNIuWQnuR70JMeuBAEA?view)
[Setup LOC CLI Environment](https://hackmd.io/igLh4azUT2aI8Fv-q-0e-g)
[LOC CLI Installation](https://hackmd.io/igLh4azUT2aI8Fv-q-0e-g?view#Download-LOC-CLI)
[LOC CLI Commands](https://hackmd.io/R4mrz2t1QSyTCHH73_2itg?view)
[Local Simple Runtime Execution](https://hackmd.io/JhAMB49rS4CrpNdhHed7YA)
# Getting Started - Hello World (JavaScript)
In this tutorial, we are going to create a simple LOC data process using JavaScript.
This data process would receive a POST request with JSON data, which contains a ```name``` field. It would return a response including this message:
```json
{
message: Hello, <name>!
}
```
## Create a Data Process
:::info
See the ++[**setup guide**](https://hackmd.io/igLh4azUT2aI8Fv-q-0e-g)++ for how to prepare your local LOC CLI environment, including getting a .yaml profile file. We also assume you are have renamed your LOC CLI to ```loc```.
You can also open the LOC CLI workspace directory (for example, ```/FST```) in VS Code (File -> Open Folder...).
:::
### Generate a Data Process Template
In your LOC CLI workspace directory (```FST``` in our example), create a new data process template with
```bash
loc new hello-world
```
You should see a new template folder called "hello-world" that contains
```
FST
hello-world
generic-logic
1.js
2.js
aggregator-logic.js
api-route-config
config.yaml
package.json
```
### Template Configuration
First look at the ```config.yaml``` in the directory:
```yaml
version: 0.1.0
name: hello-world
description: description
timeoutSeconds: 180
aggregatorLogic:
name: aggregator
file: aggregator-logic.js
genericLogics:
- name: generic-1
file: 1.js
- name: generic-2
file: 2.js
```
This file contains key information of the data process, including time out and the file name/order of generic logics. For now, we will not change anything here, but keep in mind you can configure them as you like.
## Implement Logics
### Generic Logics #1
The 1^st^ generic logic reads the ```name``` field from JSON data, converts it into Unicode string and stores it in the session storage of the data process:
:::info
The session storage is to read and write temporary data between logics during the same execution task of a data process.
Please note that the data kept via this way (session storage) can *only* be accessed by the same data process. The data would also be cleaned up once the data process finishes the task.
:::
```javascript
/**
*
* The codes in 'run' are executed when no error occurrs in Generic Logic.
*
*/
export async function run(ctx) {
// a function that transforms byte array to string
const UTF8ArrToStr = (aBytes) => {
const utf8decoder = new TextDecoder();
return utf8decoder.decode(new Uint8Array(aBytes));
}
// read and parse JSON data from the request body
const payload = JSON.parse(UTF8ArrToStr(ctx.payload.http.body));
// log payload content
ctx.agents.logging.info({ payload: payload });
// extract name from payload (default value is "World")
const name = payload.name || "World";
// write name into session storage
await ctx.agents.sessionStorage.putString("name", name);
}
/**
*
* The codes in 'handleError' is executed when an error occurrs in Generic Logic,
* or the CURRENT running Logic just gets an error.
*
*/
export async function handleError(ctx, error) {
ctx.agents.logging.error(error.message); // log the error
}
```
:::info
See ++[**Agent List**](https://hackmd.io/Uj-tC7l9Q82VyGr8R5PL2Q)++ for reference of LOC agents.
Please note that ```run()``` and ```handleError()``` require the ```export``` keyword for the LOC CLI will compile them before uploading. If you want to write this code directly in LOC Studio, please remove the ```export``` keywords.
:::
### Generic Logic #2
The 2^nd^ generic logic reads the ```name``` from session storage and send an event.
```javascript
/**
*
* The codes in 'run' is executed when no error occurred in Generic Logic.
*
*/
export async function run(ctx) {
// read name from session store
const name = await ctx.agents.sessionStorage.get("name");
const events = [
{
sourceDID: "Hello_World", // source DID
targetDID: name, // target DID will be user's name
labelName: `Hello, ${name}!`, // event label (greeting message)
meta: "", // meta (empty)
type: "default", // default group
},
];
// emit an event to event store
await ctx.agents.eventStore.emit(events);
// log event
ctx.agents.logging.info(`emit event: ${JSON.stringify(events)}`);
}
/**
*
* The codes in 'handleError' is executed when there is any error occurred
* in Generic Logic or CURRENT running Logic just gets an error.
*
*/
export async function handleError(ctx, error) {
ctx.agents.logging.error(error.message); // log the error
}
```
### Aggregator Logic
The aggregator logic also reads the ```name``` from sessoin storage and send a response to the caller.
```javascript
/**
*
* The codes in 'run' are executed when no error occurrs in Aggregator Logic.
*
*/
export async function run(ctx) {
// read name from session store
const name = await ctx.agents.sessionStorage.get("name");
const response = {
message: `Hello, ${name}!`
};
// send response to API route
ctx.agents.result.finalize({
status: "ok",
taskId: ctx.task.taskId,
response: response
});
// log response
ctx.agents.logging.info({ response: response });
}
/**
*
* The codes in 'handleError' is executed when an error occurrs in Generic Logic,
* or the CURRENT running Logic just gets an error.
*
*/
export async function handleError(ctx, error) {
ctx.agents.logging.error(error.message); // log the error
}
```
## Deploy the Data Process
Deploy ```hello-world``` to LOC with your profile ```example```:
```bash
loc deploy hello-world -p example
```
:::info
You'll have to login LOC first and also need a profile file. See ++[**Setup LOC CLI Environment**](https://hackmd.io/igLh4azUT2aI8Fv-q-0e-g)++ for more details.
:::
You will see output like this:
```
👀 Get baseURL and namespace...
🔍 Check Folder Name: hello-world...
💾 Deploy logics...
Generated an empty chunk: "1"
Generated an empty chunk: "2"
Logic Build Complete, save file to \FST\hello-world/build/generic-logic/1.js
Logic Build Complete, save file to \FST\hello-world/build/generic-logic/2.js
Successfully post generic logic result...
PERMANENT IDENTITY NAME REVISION CREATED TIME
------------------------------------ --------- -------- ---------------------------
a16b45b0-9c9d-4033-82cf-0e26a4b926e7 generic-1 1 2022-05-18T02:01:20.247809Z
Successfully post generic logic result...
PERMANENT IDENTITY NAME REVISION CREATED TIME
------------------------------------ --------- -------- ---------------------------
041a58f4-53aa-439b-8509-280f1c60d2e2 generic-2 1 2022-05-18T02:01:20.301210Z
Logic Build Complete, save file to \FST\hello-world/build/aggregator-logic.js
Successfully post aggregator logic result...
PERMANENT IDENTITY NAME REVISION CREATED TIME
------------------------------------ ---------- -------- ---------------------------
684e0acf-f95f-435f-ae6d-b81a6eb0224b aggregator 1 2022-05-18T02:01:21.044536Z
💾 Deploy data process...
⠐ Waiting for data process...
Successfully post data process result...
PERMANENT IDENTITY NAME REVISION ENABLED CREATED TIME
------------------------------------ ----------- -------- ------- ---------------------------
e82c50f2-646d-49b9-940a-1ac86589d3ca hello-world 1 true 2022-05-18T02:01:23.541078Z
```
If the data process is successfully deployed, select and copy the **PID** (Permanent IDentity; in our case it's ```e82c50f2-646d-49b9-940a-1ac86589d3ca```). We will need it to configure our API route.
## Inspect Data Process List
```bash
loc dp list
```
You can also inspect your data process(es) in this way:
```
list data processes
PERMANENT IDENTITY NAME REVISION ENABLED CREATED TIME
------------------------------------ ------------------------ -------- ------- ---------------------------
1c2548af-690d-4c6c-8dc2-8ca7b0cccfdb general-demo-docgen 1 true 2022-05-13T09:00:06.831490Z
e82c50f2-646d-49b9-940a-1ac86589d3ca hello-world 1 true 2022-05-18T02:01:23.541078Z
f646641a-e96d-49af-a415-5c3263c85096 general-demo-writeoff 1 true 2022-05-13T10:04:59.959877Z
...
```
## Deploy a API Route
The ```api-route-config.yaml``` in the project root directory is the configuration file for deploying a new API route:
```yaml
method: GET
mode: Sync
encapsulation: true
name: this-is-an-example
path: /this/is/an/example/path
dataProcessPids:
- pid: 00000000-0000-0000-0000-000000000000
revision: latest
```
We'll change it like this (using POST and the API route ```/hello-world/hello```):
```yaml
method: POST
mode: Sync
encapsulation: true
name: hello-world-api
path: /hello-world/hello
dataProcessPids:
- pid: e82c50f2-646d-49b9-940a-1ac86589d3ca
revision: latest
```
:::info
Remember to update the PID of the data process you want to trigger with this API route. You can even trigger multiple data processes by adding more PIDs here.
:::
Now deploy the API route:
```bash
loc ar deploy -f hello-world/api-route-config.yaml
```
The output would be like this:
```
{
method: 'POST',
mode: 'Sync',
encapsulation: true,
name: 'hello-world-api',
path: '/hello-world/hello',
dataProcessPids: [ { pid: 'e82c50f2-646d-49b9-940a-1ac86589d3ca', revision: 1 } ]
}
Successfully Post Api Route '197cb39a-4cc7-46ba-9a58-b722f217e191'...
ID NAME ENABLED PATH METHOD MODE
------------------------------------ --------------- ------- ------------------ ------ ----
197cb39a-4cc7-46ba-9a58-b722f217e191 hello-world-api true /hello-world/hello POST Sync
```
The PID of our API route is ```197cb39a-4cc7-46ba-9a58-b722f217e191```.
## Inspect API Route List
```bash
loc ar list
```
Display all deployed API routes:
```
list api route
ID NAME ENABLED PATH METHOD MODE
------------------------------------ -------------------------------- ------- ----------------------- ------ ----
526369a7-0efa-4b53-bfdc-7db2bbbc3c43 general-demo-policy true /demo/v1/policy GET Sync
3c874fef-b968-4af4-a6eb-1d949121e864 general-demo-docgen true /demo/v1/docgen POST Sync
197cb39a-4cc7-46ba-9a58-b722f217e191 hello-world-api true /hello-world/hello POST Sync
...
```
## Deploy Data Process and API Route at the Same time
There's another way you can deploy a data process with an API route together:
```bash
loc deploy hello-world -ar
```
This will deploy ```hello-world``` and the API route ```hello-world-api``` together. The PID of ```hello-world``` will be automatically link up to the API route (it doesn't matter what PID you've written in ```api-route-config.yaml```).
:::info
```./loc deploy hello-world-ts -ts -ar``` replaces the API route but will still upload a new data process. You need to manually delete the older one(s) in order to release unused resources.
:::
## Invoke Data Process
You can use an API client tool such as **[Postman](https://www.postman.com/)** or **[Insomnia](https://insomnia.rest/)** to invoke the data process via your API route.
For example, we will send a POST request to ```https://api.loc.xxxxx/hello-world/hello``` (the server path is the ```baseURL``` in your profile file) with the following JSON payload:
```json
{
"name": "Arthur Dent"
}
```
We will get a result similar to this:
```json
{
"_status": 200,
"_metadata": {
"executionId": "YoRT5Rjdd1nd-iH-Ht8GAA",
"status": "success",
"expiration": "2022-05-21T02:03:17.915121653Z"
},
"data": {
"status": "ok",
"taskId": {
"executionId": "YoRT5Rjdd1nd-iH-Ht8GAA",
"id": "Q8NBEOrm1GiOMdgObxTa1Q"
},
"response": {
"message": "Hello, Arthur Dent!"
}
}
}
```

You can see the data process has been successfully invoked and our custom response is embedded under the ```data``` field.
If you login LOC Studio you can also find the detail of the event we've sent in generic logic #2:
```json
{
"key": 1,
"index": 1,
"timestamp": "2022-05-18T02:03:17.987Z",
"labelName": "Hello, Arthur Dent!",
"sourceDigitalIdentity": "Hello_World",
"targetDigitalIdentity": "Arthur Dent",
"executionId": "YoRT5Rjdd1nd-iH-Ht8GAA",
"meta": "",
"taskId": "Q8NBEOrm1GiOMdgObxTa1Q",
"logicIdentityContext": {
"permanentIdentity": "041a58f4-53aa-439b-8509-280f1c60d2e2",
"revision": 1,
"name": "generic-2"
},
"dataProcessIdentityContext": {
"permanentIdentity": "e82c50f2-646d-49b9-940a-1ac86589d3ca",
"revision": 1,
"name": "hello-world"
}
}
```
:::info
If you see status code ```404```, it might be that the data process or API route haven't be taken effect in LOC. You can try a few minutes later.
If you see status code ```202``` (the data process has been triggered but cannot finish task) , it may be that your LOC environment has too many processes running. Please check with your Ops Team or your contact at FST Network.
:::
## Remove Data Process/API Route
Delete a data process with specific PID:
```bash
loc dp delete <data process pid>
```
Delete an API route with specific PID:
```bash
loc ar delete <api route pid>
```
---
<text style="font-size:17pt">**LOC CLI Guidebook Catalogue**</text>
<text style="font-size:13pt"> [LOC CLI Introduction](https://hackmd.io/J5r2l2OaRgKF9LACR5KHsg?view)</text>
<text style="font-size:13pt"> [LOC Concept](https://hackmd.io/mwTxDdBjSuiKrAmainQZAA?view)</text>
<text style="font-size:13pt"> [LOC CLI Commands](https://hackmd.io/R4mrz2t1QSyTCHH73_2itg?view)</text>
<text style="font-size:13pt"> [Getting Started - JavaScript](https://hackmd.io/IiHvmAtjTTGFfakaH0dWuw?view)</text>
<text style="font-size:13pt"> [Getting Started - TypeScript](https://hackmd.io/kz93Th7vTCCbO3GFxp3r-A?view)</text>
<text style="font-size:13pt"> [Reference - Agent List](https://hackmd.io/Uj-tC7l9Q82VyGr8R5PL2Q?view)</text>
<text style="font-size:13pt"> [Reference - Event Fields Comparison Table](https://hackmd.io/N2Km6-8kRI2tMR5X4tRHeQ?view)</text>
###### tags: `LOC CLI`