Theme
The JavaScript dialect Preview
SyncJS is JavaScript. There is no transpiler and no build step: the source you type into the console is the source the engine compiles. The engine is an embedded interpreter written in Go, not a browser and not Node.js.
What the language supports
ECMAScript 5.1 in full, plus most of what came after. All of the following have been verified to work in the Connector:
| Feature | Status |
|---|---|
let, const, block scope | Works |
| Arrow functions | Works |
| Template literals | Works |
| Classes | Works |
| Destructuring, default parameters, rest and spread | Works |
for...of, iterators, generators | Works |
Map, Set | Works |
Promise | Defined, but see the warning below |
String.prototype additions: startsWith, endsWith, includes, repeat, padStart, trim | Works |
Array.prototype additions: includes, find, findIndex | Works |
Object.assign, Object.keys, Object.entries | Works |
JSON, Math, Date, RegExp including named capture groups | Works |
The classic style, var plus function expressions, is used throughout this manual because it is what the Syncplify Server examples use and it copies cleanly between the two products. Nothing stops you writing modern code.
What is deliberately absent
| Missing | Use instead |
|---|---|
console.log and the whole console object | Log() |
fetch, XMLHttpRequest | HttpCli |
require("fs"), require("http") and the rest of the Node standard library | The local file and HTTP functions |
process, Buffer, __dirname | Nothing equivalent; the engine is not Node |
window, document, the DOM | Nothing equivalent; there is no browser |
npm, package.json, import and export | require() against files you place yourself |
console.log being undefined is the single most common surprise. A script that calls it stops at that line with a TypeError and, on a fail closed before handler, refuses the transfer. Use Log().
Timers and asynchrony
setTimeout, setInterval, setImmediate and their clear counterparts are defined, and Promise exists, but they are almost never the right tool here.
Deferred work runs after the script body, not during it
The engine runs your source top to bottom, then drains whatever timers and promise callbacks are still queued, all inside the same handler timeout. A callback therefore cannot influence a before handler's verdict: by the time it runs, the decision to allow or refuse has already been taken from the main body.
Anything a script needs to know, it must fetch synchronously, which the whole standard library is built to do. To pause, use Sleep(), which blocks properly and counts against the timeout as you would expect. To do slow work, put it on an after handler marked Run in the background.
Errors
An uncaught exception ends the script and reports failure to the handler. On a fail closed before handler that refuses the operation, which is usually what you want from a policy gate that broke.
try/catch works normally, and it also catches the errors thrown by the engine's own functions, so you can handle a refused call and carry on:
js
try {
Log.Info(Session.GetRemoteAddress());
} catch (e) {
Log.Warn("not available on a Connector: " + e);
}One exception is worth knowing about: a failed new VirtualFS(...) or new VirtualFSByName(...) cannot be caught. It ends the script immediately, and any try around it is not consulted. Check your arguments before constructing, rather than constructing and hoping to recover. See The virtual file system object.
Loading your own modules
require() is available and loads CommonJS modules from a folder on the Connector host.
js
var greet = require("greet"); // loads greet.js from the modules folder
Log.Info(greet.hello("world"));js
// greet.js
module.exports = {
hello: function (name) { return "hello " + name; }
};The folder is modules inside the Connector's data directory:
| Platform | Path |
|---|---|
| Windows | C:\ProgramData\Syncplify\sc-conn\modules |
| Linux, macOS, FreeBSD | /opt/Syncplify/sc-conn/modules |
| Docker | /data/modules on the mounted volume |
Create the folder if it is not there. A require() of a name that has no matching file throws GoError: Invalid module.
Nothing is preinstalled
Unlike Syncplify Server, the Connector ships no bundled modules, and require("underscore-min") fails on a fresh install. If you want Underscore, Lodash or anything else, download the single file build into the modules folder yourself, and remember that you are placing third party code onto the machine that holds your files.
Modules are not synchronized and not backed up by SFTP.cloud
The modules folder is an ordinary directory on your host. It is not part of the Connector's database, so it does not travel with a database restore, is not replicated to another Connector, and is not included in anything the Portal holds. If a script depends on a module, deploying that script to a second Connector means copying the module too, and rebuilding a host means putting it back.
Many Node modules work, because most pure JavaScript libraries have no Node dependencies. Anything that reaches for fs, http, Buffer or process will not.