Scripting
TypeScript API reference
Reference the async execution model, binary-safe Redis facade, utility globals, permissions, and transformer inputs available to Varc scripts.
Varc runs TypeScript and JavaScript in its built-in scripting engine. Scripts support standard language features such as Array, Map, Date, Promise, and typed arrays, plus the Varc APIs documented on this page.
Execution and return values
Top-level await works in every execution class. Only an explicit return supplies the terminal result:
const values = await Promise.all([redis.get("one"), redis.get("two")]);
return values;
Use return await operation when returning a Promise directly. Varc rejects unresolved Promises and Promises nested inside returned arrays or objects rather than publishing a misleading partial result.
Redis, Fetch, and sleep are asynchronous and share the script’s cancellation and execution deadline. Varc allows up to 64 operations to wait at once and stops the script if that bound is exceeded.
Redis values and keys
Redis keys, fields, and members are binary-safe:
type RedisBytes = Uint8Array;
type RedisKey = string | Uint8Array;
Text helpers decode bulk strings as UTF-8 for convenience. Use the corresponding byte method or redis.call when exact bytes matter. Integer replies use number when safe and bigint when the value exceeds JavaScript’s safe-integer range.
Redis facade
redis.database is the immutable logical database targeted by the facade. redis.db(index) returns another complete facade routed to index; it does not mutate the root object.
| Method | Result | Purpose |
|---|---|---|
redis.db(index) |
Redis |
Route subsequent calls through another logical database. |
redis.call(name, ...args) |
Promise<unknown> |
Issue any command allowed by policy while preserving the raw reply shape and bytes. |
redis.text(value) |
decoded value | Decode a byte reply element as UTF-8. |
redis.textArray(value) |
decoded array | Decode each byte reply element as UTF-8. |
Use redis.call(name, ...args) as the supported raw-command escape hatch when a typed helper is not available.
Strings
| Method | Return |
|---|---|
get(key) |
Promise<string | null> |
getBytes(key) |
Promise<Uint8Array | null> |
set(key, value, ...options) |
Promise<string | null> |
setnx(key, value) |
Promise<number> |
getset(key, value) |
Promise<string | null> |
append(key, value) |
Promise<number> |
strlen(key) |
Promise<number> |
incr(key) / decr(key) |
Promise<number> |
incrBy(key, amount) / decrBy(key, amount) |
Promise<number> |
mget(...keys) |
Promise<(string | null)[]> |
Keys and expiry
| Method | Return |
|---|---|
del(...keys) / unlink(...keys) |
Promise<number> |
exists(...keys) |
Promise<number> |
expire(key, seconds) / pexpire(key, milliseconds) |
Promise<number> |
persist(key) |
Promise<number> |
ttl(key) / pttl(key) |
Promise<number> |
type(key) |
Promise<string | null> |
rename(key, newKey) |
Promise<string | null> |
Hashes
| Method | Return |
|---|---|
hget(key, field) |
Promise<string | null> |
hset(key, field, value) |
Promise<number> |
hdel(key, ...fields) |
Promise<number> |
hexists(key, field) |
Promise<number> |
hlen(key) |
Promise<number> |
hgetall(key) |
Promise<Record<string, string>> |
Use redis.call("HGETALL", key) when fields or values may not be UTF-8 and must remain bytes.
Lists
| Method | Return |
|---|---|
lpush(key, ...values) / rpush(key, ...values) |
Promise<number> |
lpop(key) / rpop(key) |
Promise<string | null> |
llen(key) |
Promise<number> |
lrange(key, start, stop) |
Promise<string[]> |
Sets
| Method | Return |
|---|---|
sadd(key, ...members) / srem(key, ...members) |
Promise<number> |
scard(key) |
Promise<number> |
sismember(key, member) |
Promise<number> |
smembers(key) |
Promise<string[]> |
Sorted sets
| Method | Return |
|---|---|
zadd(key, score, member) |
Promise<number> |
zrem(key, ...members) |
Promise<number> |
zcard(key) |
Promise<number> |
zscore(key, member) |
Promise<number | null> |
zrange(key, start, stop, ...options) |
Promise<string[] | { value: string; score: number }[]> |
Server and incremental scans
| Method | Return |
|---|---|
ping() |
Promise<string | null> |
dbsize() |
Promise<number> |
scan(cursor, options?) |
Promise<{ cursor: string; keys: string[] }> |
sscan(key, cursor, options?) |
Promise<{ cursor: string; members: string[] }> |
hscan(key, cursor, options?) |
Promise<{ cursor: string; fields: Record<string, string> }> |
zscan(key, cursor, options?) |
Promise<{ cursor: string; members: { value: string; score: number }[] }> |
keys(pattern?, options?) |
Promise<string[]> |
scan options are { match?, count?, type? }. Continue until the returned cursor is "0".
redis.keys() is not the blocking Redis KEYS command. It collects results by repeatedly calling SCAN and stops at Varc’s scan-iteration and returned-key quotas. Prefer explicit scan loops when the caller should process one bounded page at a time.
Command policy
All helpers and redis.call pass through one command-policy gate. Manual scripts and macros may perform ordinary reads and writes, but Varc rejects destructive administration, connection-affine commands, subscriptions, server-side Lua, and Redis Functions. Examples include FLUSHALL, CONFIG, CLIENT, SELECT, MULTI, EVAL, SCRIPT, FCALL, and FUNCTION.
Transformers deny every Redis command. Dashboard widgets use a separate read-only policy described in execution classes.
Environment variables
env is a frozen record containing the active Script environment:
const endpoint = env.API_ORIGIN;
return { environmentConfigured: endpoint !== undefined };
Member completion reflects the environment selected in the workspace status bar. Reading a declared secret that has no value on this device throws scriptSecretUnavailable. Values printed or returned by a script are not redacted. See environments and permissions.
Byte and text codecs
| Global | Methods | Behavior |
|---|---|---|
base64 |
encode(value), decode(text) |
Strict standard Base64 with mandatory padding; decode returns bytes. |
hex |
encode(value), decode(text) |
Lowercase output; decode accepts either case and returns bytes. |
utf8 |
encode(text), decode(bytes) |
Strict UTF-8 conversion in both directions. |
Invalid input fails instead of being repaired or guessed.
Hashing and randomness
| Global | Signature | Notes |
|---|---|---|
hash.sha1 |
(value: string | Uint8Array) => Uint8Array |
Legacy interoperability only. |
hash.sha256 |
(value: string | Uint8Array) => Uint8Array |
SHA-256 digest bytes. |
hash.md5 |
(value: string | Uint8Array) => Uint8Array |
Legacy interoperability only. |
hash.hmacSha256 |
(key, value) => Uint8Array |
HMAC-SHA256 tag bytes. |
uuid |
() => string |
Random RFC 4122 version 4 UUID. |
randomBytes |
(length: number) => Uint8Array |
Cryptographically random bytes, up to 64 KiB. |
crypto.getRandomValues |
(target: Uint8Array) => target |
Web-compatible in-place random fill. |
crypto.randomUUID |
() => string |
Web-compatible random UUID. |
Use hex.encode(hash.sha256(value)) when a hexadecimal digest is required. Use varc:seed rather than these globals for repeatable fixture data.
Cooperative sleep
await sleep(milliseconds) pauses without busy-spinning. It uses the run’s host-I/O queue and shares the same deadline and cancellation budget.
for (let attempt = 0; attempt < 5; attempt += 1) {
if (await redis.exists("job:complete")) return true;
await sleep(100);
}
return false;
Console
console.log, console.info, console.warn, console.error, and console.debug write bounded messages to Run output. Varc caps the number and size of retained messages and reports how many were dropped.
Host capabilities
The following globals exist in manual scripts and macros, but each saved script needs the corresponding permission:
| Global | API | Permission |
|---|---|---|
clipboard |
write(value) |
Clipboard |
dialog |
info(message), warn(message), error(message) |
Dialogs |
notifications |
show(title, body?) |
Notifications |
fetch |
fetch(input, init?) |
Network |
Clipboard access is write-only. Dialog and notification calls are fire-and-forget. All are size- and rate-limited. See environments and permissions and the full Fetch API reference.
Fetch and web-compatible globals
Network-enabled scripts and macros also receive Request, Response, Headers, Blob, FormData, AbortController, AbortSignal, ReadableStream, URL, URLSearchParams, TextEncoder, and TextDecoder.
These globals implement the documented Fetch workflow; they do not install a browser DOM, navigation, cookie store, service workers, arbitrary sockets, or Node APIs.
Transformer input
Only transformer runs receive:
declare const value: Uint8Array;
declare const complete: boolean;
value contains the exact bytes being decoded. complete is currently always true; truncated values are not sent to transformers. A transformer returns a bounded render result and cannot access Redis, Fetch, or host capabilities.