[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!" } } } ``` ![](https://hackmd.io/_uploads/SkDOBCWvq.png) 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`