Skip to content

TINN API

Francesco Saverio Castellano edited this page Mar 30, 2020 · 22 revisions

The TINN shell and interpreter exports the following symbols to the javascript context:

  • os: object that provides functionalities to interact with the OS (writing and reading files, executing commands, etc)
  • path: cross platform path manipulation functions
  • process: object that provides information regarding the current running process
  • require: function to load javascript modules
  • __filename, __dirname: the filename and directory of the current script
  • load: a function to load and run javascript files in the current scope (e.g. load('./myscript.js'))

List of functions in os

os.exec(array command, [bool close])
Executes the command whose arguments are specified in the array and returns the resulting output and exit code.
The command array must contains the full path of the command and all arguments that must be passed to it.
When the optional argument close is provided and set to true, this call immediately returns after executing the command, without reading the output.
The return value is an object with two attributes:

  • result: an integer whose value is the exit status of the command(0 when the command is successful and 1 when the command failed to execute)
  • output: the command output as a string. This attribute is only present if the close argument is not set to true
    The following examples executes grep nginx to get the PID of the nginx process:
var pid = OS.exec(["/usr/bin/pgrep", "nginx"]).output;

 
os.filesize(string path)
Returns the size of the file in bytes or -1 is the file is not found.  
 
os.lastModifiedTime(string path)
Returns the last modified time of the file specified by path as a UNIX timestamp.  
 
os.unlink(string path)
Removes the file specified in path. Returns 0 on success and -1 on failure.  
 
os.mkdir(string path)
Creates the directory specified in path or returns -1 on failures.  
 
os.rmdir(string path)
Removes the directory specified in path. Returns 0 on success and -1 on failure.  
 
os.mkpath(string path)
Creates the directory three specified in path. Returns 0 on success and -1 on failure.  
 
os.listDir(string path, [string ext])
Returns an array with all files in the directory specified in path. If ext is given then only the files ending with ext are returned.  
 
os.isFileAndReadable(string path)
Returns true is the file specified in path exists and is readable (path exists and it is a file).  
 
os.isDirAndReadable(string path)
Returns true is the directory scpecified path exists and is readable (path exists and it is a directory).    
os.readFile(string path)
Returns the file specified in path and returns its content in a string.  
 
os.writeFile(string path, string content)
Writes content into the file specified in path.  
 
os.fopen(string path, string mode)
Opens the file specified in path with the requested access mode. The access mode accepts the same flags as the C fopen function ('r' for reading, 'w' for writing, 'r+' for read and write, etc.).
Returns an integer that represents the file descriptor.
The following examples shows how to open a file for read and write:

var fd = OS.fopen("file.txt", "r+");

 
os.fseek(integer fd, integer offset)
Sets the internal write/read cursor of the file descriptor identified by fd to the specified offset.
After executing seek all subsequent read/write operations are relative to the offset that was set.
 
 
os.writeBytes(integer fd, array bytes)
Write bytes to the file descriptor identified by fd.
The following example shows how to open a binary file for writing and writing an array of bytes to it:

var fd = OS.fopen("file.txt", "wb");
os.writeBytes(fd, [5, 10, 20]);

 
os.readBytes(integer fd, integer count)
Reads count bytes from the file descriptor identified by fd and returns them in an array.
Depending on the current offset, the size of the file and the value of count the number of bytes returned in the array might be lower than the requested count if the end of the file is reached.  
 
os.writeString(integer fd, string text)
Writes text to the file descriptor identified by fd.
 
 
os.readString(integer fd, integer count)
Reads a string of length count from the file descriptor identified by fd.
Depending on the current offset, the size of the file and the value of count the length of the string returned might be lower than the requested count if the end of the file is reached.  
 
os.fclose(integer fd)
Closes the file identified by the file descriptor fd.
 
 
os.cwd()
Returns the current-working-directory.  
 
os.gethostname()
Returns the hostname of the current machine.  
 
os.sleep(integer milliseconds)
Pauses the execution of the current worker for the requested amount of milliseconds.  
 
os.getEnv(string name, string defaultValue)
Gets the value of the environment variable identified by name and returns its value as a string.
If defaultValue is provided then when no such variable is found defaultValue is returned.  
 
os.setEnv(string name, string value)
Sets the value of the environment variable identified by name.  
 

Paths manipulation functions

The path object contains the following functions:

path.dirname(string file)
Returns the directories of the file path.  
 
path.basename(string file)
Returns the file name in the file path.  
 
path.resolve(string dir, [string dir, string dir])
Resolves the provided sequence of path-segments into an absolute path.  
 
path.join(_string dir, [string dir, string dir])
joins all given path segments together using the platform-specific separator as a delimiter, then normalizes the resulting path.  
 
path.relative(string from, string to)
Returns the relative path from from to to based on the current working directory. If from and to each resolve to the same path (after calling path.resolve() on each), a zero-length string is returned.  
 
path.extname(string from, string to)
Returns the extension of the path, from the last occurrence of the . (period) character to end of string in the last portion of the path.  
 
path.isAbsolute(string path)
Returns true or false depending on wehther the path is an absolute path.  
 
path.normalize(string path)
Normalizes the given path, resolving '..' and '.' segments.
When multiple, sequential path segment separation characters are found (e.g. / on POSIX and either \ or / on Windows), they are replaced by a single instance of the platform-specific path segment separator (/ on POSIX and \ on Windows). Trailing separators are preserved.  
 
In addition to the above functions path.sep provides the platform-specific path segment separator.

process object

The process object contains the following properties:

  • platform: string that represents the underlying OS. Its value is win32 under Windows and linux under Linux
  • execPath: string that contains the execution path of the running process
  • env: object that contains all environment variables in a k/v form
  • version: string that contains the v8 version
  • cwd: function that returns the current working directory
  • mainModule: initial javascript module that was loaded (see section about require function)

The require function

If you are familiar with NodeJS then you already know what require is about: it is the basis of the modules loading system.
When a javascript file is loaded from another file with require, it is treated as a javascript module. This means that its code runs in an isolated scope so that all symbols (variables, functions, etc.) defined by it do not pollute the global object. A module can export symbols to the loading file by adding properties to an object called exports.
Let's show how this works with an example taken from the NodeJS documentation which also applies to TINN, consider a file with this code:

const circle = require('./circle.js');
console.log(`The area of a circle of radius 4 is ${circle.area(4)}`);   

The above code loads another javascript file called circle.js that must be located in its same directory.
Here are the contents of circle.js:

const { PI } = Math;

exports.area = (r) => PI * r ** 2;

exports.circumference = (r) => 2 * PI * r;

he module circle.js has exported the functions area() and circumference(). Functions and objects are added to the root of a module by specifying additional properties on the special exports object.
Variables local to the module will be private, because the module is wrapped in a function by TINN. In this example, the variable PI is private to circle.js.
The module.exports property can be assigned a new value (such as a function or object).
 
Below, bar.js makes use of the square module, which exports a Square class:

const Square = require('./square.js');
const mySquare = new Square(2);
console.log(`The area of mySquare is ${mySquare.area()}`);

The square module is defined in square.js:

// Assigning to exports will not modify module, must use module.exports
module.exports = class Square {
  constructor(width) {
    this.width = width;
  }

  area() {
    return this.width ** 2;
  }
};

When calling require the argument passed to it represents the javascript module that is to be loaded. The value of the module argument can either be a relative path of the module with respect to the location of the current script or a module name.

Example of require for a module loaded from its relative path:

require('./mymodule.js');

Example of require for a module loaded from its name:

require('mymodule.js');

It is also possible to omit the .js extension from the name:

require('mymodule');

When loading a module from its name, TINN uses this logic to locate the actual file:

  • if the TINN_PATH environment variable is set, then TINN looks for the module in the directory specified in TINN_PATH
  • if TINN_PATH isn't set, then TINN looks for the module in a directory called tinn_modules inside process.execPath. If the module isn't found then TINN looks for it in a directory called tinn_modules inside the current working directory (process.cwd())

After using the above logic to determine in which directory to look for the requested module, this is what TINN does to find the actual file:

  • first TINN looks for the file called mymodule.js in the directory
  • if the file isn't found then TINN looks for the presence of a directory called mymodule. If such directory is found, then TINN looks for a file called mymodule.js inside it
  • If the file isn't found then TINN looks for the project file of the module. The project file is called package.json and it contains various metadata relevant to the module. If package.json exists in the directory, then TINN parses it and looks for a property called main whose value determines what file must be loaded by TINN for the requested module. For instance, assuming that in project.json the property main is set to index.js then TINN will load index.js.

__filename and __dirname variables

This two variables are always defined and represent the filename and the directory of the current script.

load function

In addition to require TINN also offers a more simple way of executing scripts: the load function. This function reads the content of the requested script and processes it in the current scope. The argument passed to load is the path of the requested script relative to the current one.