Theme
Utilities Preview
Path pieces
js
function ExtractPath(fullPath: string): string; // the directory part
function ExtractName(fullPath: string): string; // the file name including extension
function ExtractExt(fileName: string): string; // the extension including the dotThese are string operations. They do not touch storage and do not care whether anything exists.
js
ExtractPath("/docs/sheets/budget.xlsx"); // "/docs/sheets"
ExtractName("/docs/sheets/budget.xlsx"); // "budget.xlsx"
ExtractExt("/docs/sheets/budget.xlsx"); // ".xlsx"
ExtractExt("/backups/archive.tar.gz"); // ".gz", only the last segment counts
ExtractExt("/etc/hostname"); // "" when there is no extensionA common shape, refusing an upload by extension:
js
var ext = ExtractExt(CtxRelPath()).toLowerCase();
if (ext === ".exe" || ext === ".dll" || ext === ".scr") {
Log.Warn("refused " + ext + " upload by " + CtxUsername() + ": " + CtxRelPath());
Exit(1);
}Sleep
js
function Sleep(milliseconds: number): void;Pauses the script. Unlike browser JavaScript there is no callback and no promise: execution simply stops and resumes.
js
Log.Info("waiting a moment");
Sleep(1000);
Log.Info("carrying on");Sleep spends the handler's timeout, and a user's patience
The pause counts against the handler timeout like any other work. Sleep(10000) inside a handler with the default 5000 ms budget guarantees a timeout, which on a fail closed before handler refuses the transfer. On a before handler, a sleep is time the person at the far end spends staring at a progress bar. Put anything that needs to wait on an after handler marked Run in the background.
Dates and times
FormatDateTime
js
function FormatDateTime(format: string, when?: Date | TimeStamp | number): string;Formats a moment using simple tokens. With no second argument it formats now.
| Token | Meaning | Example |
|---|---|---|
YYYY | Four digit year | 2026 |
MM | Two digit month | 08 |
DD | Two digit day | 25 |
HH | Two digit hour, 24 hour clock | 09 |
mm | Two digit minute | 05 |
ss | Two digit second | 30 |
Tokens are case sensitive: MM is the month, mm is the minute. Everything that is not a token is copied through unchanged.
js
var stamp = FormatDateTime("YYYY-MM-DD_HH-mm-ss");
var archive = "/archive/export_" + stamp + ".zip";
// /archive/export_2026-08-25_09-05-30.zipIt accepts a JavaScript Date, a TimeStamp straight out of a listing or a stat, or epoch milliseconds:
js
var info = StatFileSystemObject("/var/inbox/upload.csv");
Log.Info("last modified " + FormatDateTime("YYYY-MM-DD HH:mm:ss", info.TimeStamp));Passing undefined or null is the same as passing nothing, so FormatDateTime(fmt, maybeMissing) formats the current time rather than failing. Passing a value that is genuinely not a date raises a catchable error, which is deliberate: quietly substituting the current time would turn a wrong argument into a wrong answer.
ToDate
js
function ToDate(when: Date | TimeStamp | number): Date;Converts a timestamp into a native JavaScript Date, so you can use the standard date methods on it.
js
var info = StatFileSystemObject("/var/inbox/upload.csv");
var when = ToDate(info.TimeStamp);
Log.Info("last modified " + when.toISOString());
Log.Info("age in days: " + Math.floor((Date.now() - when.getTime()) / 86400000));It accepts the same three things FormatDateTime does. A value it cannot convert raises a catchable error:
js
try {
var d = ToDate(somethingUncertain);
} catch (e) {
Log.Warn("not a date: " + e);
}Timestamps from listings are not Dates until you convert them
Every DirListItem carries a TimeStamp, and it is a value from the engine rather than a JavaScript Date: it has no getTime() and no toISOString(). ToDate() and FormatDateTime() both read it directly, so pass it to one of them rather than trying to use it as a Date.
For "how old is this file", you rarely need a date at all. FileAgeSecs() answers that directly for local files.
Connector 1.0 and older behaved differently here
On earlier builds ToDate(info.TimeStamp) stopped the script and FormatDateTime(fmt, info.TimeStamp) silently returned the current time instead of the file's. Both are fixed. If you are running an older Connector, update it before relying on either.
Padded numbers
js
function NumToStrPad(num: number, length: number): string;Returns the number as a string, left padded with zeroes to at least length characters. A number already that long is returned unchanged.
js
NumToStrPad(7, 3); // "007"
NumToStrPad(1234, 3); // "1234"Unique identifiers
| Call | Returns | Example |
|---|---|---|
ShortUID() | 27 character identifier that sorts by creation time | 3IPkDulGC7r3GHUxRGkoQuSjx8i |
LongUID() | Two of those concatenated, 54 characters | 3IPkDulGC7r3GHUxRGkoQuSjx8i2bYr... |
UUIDv4() | Standard RFC 4122 version 4 UUID | 02ffcf37-9583-4424-a17d-64091ec4b63e |
ShortUID() and LongUID() sort lexicographically in creation order, which makes them pleasant for file names and correlation ids.
These are identifiers, not secrets
ShortUID() and LongUID() embed a timestamp and carry limited randomness. They are fine as a correlation id, a temporary file name or a database key. They are not suitable as a token, a share link, a password reset code or anything else whose security depends on being unguessable. If you need an unguessable value, derive it from a real random source outside the script and bring it in as configuration. UUIDv4() is random, but even a UUID is a poor choice for a bearer credential.
Knowing your own execution
ScriptID(), ScriptName(), ExecutionTimeout() and ExecutionTimeLeft() are documented with the rest of the execution context on The event context.
Stopping
Exit() is documented on The event context, because on a before handler the exit code is what decides whether the operation happens.