WebApps development in ArozOS

AGI (ArozOS Gateway Interface) is an interface designed to make developing ArozOS webapp’s backend with ease. The interface language is based on Otto, a JavaScript virtual machine built into ArozOS core.

In this documentation, the AGI scripting language will be introduced and examples will be provided for those who have some experience in vanilla JS programming. If you are not familiar with vanilla JS, you can start from here.

Introduction to agi

AGI (ArozOS Gateway Interface) is a JavaScript scripting interface provided by ArozOS that allow user scope code execution with high flexibility and automation. The JavaScript VM is provided by Otto and is mostly compatible with modern JavaScript syntax. The followings describe the different ways to call & use AGI scripts. WebApp (Front-end) Request Call by WebApps by logged in users. Serve as a simple backend function like a php script does with build in authentication and permission checks.

Create New WebApp

Create New WebApp Folder Structure To create a new WebApp, create a folder under the ./web/ folder under arozos root. After the folder is created, place the following files into the folder. (Assume the module name is “MyWebapp”) . └── web/ └── MyWebapp/ ├── init.agi ├── index.html └── img/ ├── icon.png └── desktop_icon.png The icons are required to be in following sizes Icon Filename Size icon.png 64 x 64 px desktop_icon.

Start Script (init.agi)

The start script (or commonly known as the init.agi file), is the config and environment checking script that allow ArozOS to know the given folder is a WebApp instead of a resources file. This file define the way and specification on how to launch the WebApp module on the web desktop interface. Here is a minimal example of the init.agi file. /* Example Module author: tobychui This module is just an example for showcasing the basics of how agi scripting works with the front-end in ArozOS environment */ //Define the launch settings for the module var moduleLaunchInfo = { Name: "Example", Group: "Interface Module", IconPath: "Example/img/small_icon.

Request & Response

Front-end → Backend (AGI) Request When requesting the AGI execution interface, you can post data with your request. ArozOS provides two way for front-end to request the AGI script placed in your ./web/ folder. Request via ao_module wrapper (Recommended) You can import ao_module.js and use the ao_module_agirun function call to execute a agi script. Here is an example. //index.html //Call to helloworld.js with timeout set to 3 seconds ao_module_agirun("demo/backend/helloworld.js", { foo: "bar" }, function(resp){ alert(resp); },function(){ alert("Oops.

Front-end Development

Front-end development in ArozOS is no different from normal WebApp development. Basics of ArozOS WebApp ArozOS can be accessed via many different ways. The most noticeable one of course is the web desktop interface. Here is a list of possible access mode of any WebApp installed on ArozOS Web Desktop Mode (float windows) Mobile Desktop Mode (Vertical full screen float windows) Standalone mode (Normal website like) PWA Mode (Android devices only) The front-end API works on the web desktop and mobile desktop mode, while providing limited support to standalone and PWA mode users.

🔹 Float-Windows API

Requirements Float Windows (fw) are the draggable windows on the ArozOS web desktops that display the contents of WebApps. Float Windows properties can be controlled by the app front-end script using the ao_module.js api wrapper in the web/script/ folder. To use it, import the ao_module wrapper from your webapp html files. <script type="text/javascript" src="../script/jquery.min.js"></script> <script type="text/javascript" src="../script/ao_module.js"></script> Note that jquery must be imported before ao_module.js AND ao_module must be imported with relative path to current script to make sure all the ao_module functions are usable.

🔹 Select, Pass or Upload Files

Requirements Same as the use of Float-Window API, some of the functions involving ao_module wrapper will require the following library to be imported. <script type="text/javascript" src="../script/jquery.min.js"></script> <script type="text/javascript" src="../script/ao_module.js"></script> Note that jquery must be imported before ao_module.js AND ao_module must be imported with relative path to current script to make sure all the ao_module functions are usable. File Selector ArozOS has a build-in file selector which you can utilize in your WebApp as well as some utilities function to help you build a WebApp easily with file selection functions.

🔹 Requesting Media Stream

WebApp can request any files from the user accessible storage scope by making a HTTP request to the media endpoint. If you need backend processing after reading the file, use the filelib API instead. Media Stream Request To get a stream of media file from the server using virtual path, make a HTTP request to /media/ endpoint with ?file={{path}} GET parameter. Here is an example. GET /media?file=user:/Desktop/music.mp3 By default the header do not include Content-Disposition or Content-Type.

🔹 ao_module utilities

ao_module provide a list of utilities function which you can use to make developing WebApps easier. Usage To use the utilities functions, your fist need to import the ao_module wrapper as follows. <script type="text/javascript" src="../script/jquery.min.js"></script> <script type="text/javascript" src="../script/ao_module.js"></script> And call them with the static class name ao_module_utils. For example, let newUUID = ao_module_utils.getRandomUID(); //Return a random UUID from timestamp Objects Encoding 🔹 objectToAttr(object) Convert objects into a DOM attribute safe string

Backend Development

User scripting can be done in ArozOS using ArozOS Gateway Interface (agi). AGI interface documentations are labeled with prefix 🔸. Running .agi Scripts To execute agi script (with file extension of .agi or .js), call to the ao_module.js wrapper’s agi_run function. Here is a minimal example on how to call an agi script in front-end JavaScript code. ao_module_agirun("demo/backend/helloworld.js", { foo: "bar" }, function(resp){ alert(resp); }); For more details about front-end back-end interaction, see Request & Response

🔸 system

All the functions in the system library are usable in all agi runtime and do not need to include using requirelib function. CONST BUILD_VERSION INTERNVAL_VERSION LOADED_MODULES LOADED_STORAGES VAR HTTP_RESP HTTP_HEADER (Default: "text/plain") You can set HTTP_RESP with HTTP_HEADER to create custom response headers. For example, you can serve an HTML file using agi gateway HTTP_RESP = "<html><body>Hello World</body></html>"; HTTP_HEADER = "text/html"; Response Handlers sendResp("Any string"); sendJSONResp(JSON.stringify({text: "Hello World")); //ArozOS v1 / v2 sendJSONResp({foo: 'bar'}); //ArozOS v2 only Database Access newDBTableIfNotExists("tablename"); DBTableExists("tablename"); //Return true/false dropDBTable("tablename"); writeDBItem("tablename", "key", "value"); readDBItem("tablename", "key"); //Return false if read failed listDBTable("tablename"); //Return key value array deleteDBItem("tablename", "key"); Register and Packages registerModule(JSON.

🔸 user

The user library is automatically imported when the execution scope is a “user” scope instead of a “system” scope. For example, WebApp agi calls, serverless and personal homepage are all accessible to the user scope functions. CONST USERNAME USERICON USERQUOTA_TOTAL USERQUOTA_USED USER_VROOTS //Return an array of root names USER_MODULES //Accessible modules in array, might return ["*"] for admin permission Permission getUserPermissionGroup(); //Get the permission group name(s) this user are in userIsAdmin(); //Return true / false User Creation, Edit and Removal All the command in this section require administrator permission.

🔸 serverless

Serverless function are only usable in serverless execution scope. Developers can access agi and do dynamic programming via external agi call using ARZ Serverless panel. The following APIs allow devs to access GET, POST parameters and request Body on demand. CONST REQ_METHOD //Get the method of request, e.g. GET / HEAD / POST FUNCTIONS getPara(key) //Return the GET value of given key postPara(key) //Return the POST value of given key readBody() //Get the whole request body as string Notes These functions are only usable when called via the ARZ Serverless endpoints (URI start from /api/remote/)

🔸 filelib

filelib is the core library for users to interact with the file system. You can include the library with requirelib("filelib"). Example as follows. if (!requirelib("filelib")){ console.log("Filelib import failed"); }else{ console.log(filelib.fileExists("user:/Desktop/")); } Filelib functions Here is a list of functions and example provided by filelib. filelib.writeFile("user:/Desktop/test.txt", "Hello World"); //Write to file filelib.readFile("user:/Desktop/test.txt"); //Read from file filelib.deleteFile("user:/Desktop/test.txt"); //Delete a file by given path filelib.readdir("user:/Desktop/"); //List all subdirectories within this directory filelib.walk("user:/Desktop/"); //Recursive scan dir and return all files and folder in subdirs, network drive are not supported filelib.

🔸 appdata

An API for access files inside the web folder. This API only provide read only functions. Include the appdata lib as follows. requirelib("appdata"); appdata functions appdata.readFile("UnitTest/appdata.txt"); //Return false (boolean) if read failed appdata.listDir("UnitTest/backend/"); //Return a list of files in JSON string Example Usages Read File /* appdata.readFile.js This script test the appdata read file function. This should be able to read file */ //Require the appdata library var succ = requirelib("appdata"); function main(){ //Get a file from the UnitTest WebApp.

🔸 imagelib

A basic image handling library to process images. Allowing basic image resize and get image dimensions //Include the library requirelib("imagelib"); ImageLib functions imagelib.getImageDimension("user:/Desktop/test.jpg"); //return [width, height] imagelib.resizeImage("user:/Desktop/input.png", "user:/Desktop/output.png", 500, 300); //Resize input.png to 500 x 300 pixal and write to output.png imagelib.loadThumbString("user:/Desktop/test.jpg"); //Load the given file's thumbnail as base64 string, return false if failed imagelib.cropImage("user:/Desktop/test.jpg", "user:/Desktop/out.jpg",100,100,200,200)); imagelib.classify("tmp:/classify.jpg", "yolo3"); //Classify an image using neural network, since v1.119 Crop Image Options Crop the given image with the following arguemnts: 1) Input file (virtual path) 2) Output file (virtual path, will be overwritten if exists) 3) Position X 4) Position Y 5) Crop With 6) Crop Height return true if success, false if failed AI Classifier Options (since v1.

🔸 http

A basic http function group that allow GET / POST / HEAD / Download request to other web resources //Include the library requirelib("http"); http functions http.get("http://example.com/api/"); //Create a get request, return the respond body http.post("http://localhost:8080/system/file_system/listDir", JSON.stringify({ dir: "user:/Desktop", sort: "default" })); //Create a POST request with JSON payload http.head("http://localhost:8080/", "Content-Type"); //Get the header field "Content-Type" from the requested url, leave 2nd paramter empty to return the whole header in JSON string http.

🔸 websocket

websocket library provide request upgrade from normal HTTP request to WebSocket connections. //Include the library requirelib("websocket"); websocket functions websocket.upgrade(10); //Timeout value in integer, return false if failed var recv = websocket.read(); //Blocking websocket listen websocket.send("Hello World"); //Send websocket to client (web UI) websocket.close(); //Close websocket connection Usage Example Font-end function getWSEndpoint(){ //Open opeartion in websocket let protocol = "wss://"; if (location.protocol !== 'https:') { protocol = "ws://"; } wsControlEndpoint = (protocol + window.

🔸 iot

The iot library provide access to the iot hardware control endpoints (or endpoints for short) in a much easier to use abstraction. Note that not all iot devices are supported. If you have an unsupported iot device, please contribute a driver for your brand of iot devices. //Include the library requirelib("iot"); iot functions iot.ready() //Return the iot manager status. Return true if ready, false otherwise. iot.scan() //Force the iot manager to scan nearby iot devices iot.

🔸 share

The share API allow access to the ArozOS share interface and generate UUID based on the shared file. requirelib("share"); share functions share.shareFile("user:/Desktop/test.pptx", 300); //File virtual path and timeout in seconds, return UUID of share share.getFileShareUUID("user:/Desktop/test.pptx"); //Get the share UUID of a given file, return null if not shared share.fileIsShared("user:/Desktop/test.pptx"); //Return true / false share.checkShareExists(shareUUID); //Return true / false share.checkSharePermission(shareUUID); //Return the share permission of shares (anyone / signedin / samegroup), return null if shareUUID invalid.

Advance Usage

ArozOS with agi can be used to handle some advance use cases. Advance use case examples are labeled with prefix ◼️ .

◼️ Telegram Bot (Serverless)

agi when paired with serverless function, it can be used to handle external HTTP request like a webhook server does. Telegram Bot Telegram bot is one of the example in which serverless can be used to generate an integrative bot that works in telegram to automate some commands or sending stickers. Here is an example code for such usage. To use this, you will need to add this script to ARZ Serverless app and create an external request link for this script.

◼️ User Space Exec (Serverless)

When an agi script is executed in user serverless scope, developer can utilize the filelib with JavaScript build in eval() function to make some fun use of dynamic script importing. Import and Execution in User Space Here is an example of importing moment.min.js and execute it in user space. requirelib("filelib"); var momentLib = filelib.readFile("user:/moment.min.js"); eval(momentLib); Note that when paired with the http library, this might cause some security issues. That is why the ARZ Serverless app will remind you not to include untrusted script into the library to prevent any illegal access or attack from happening to your server.