Utilities
AGS comes with some builtin utilities for common operations.
File functions
Reading files
import { readFile, readFileAsync } from "ags/file"
function readFile(path: string): string
function readFileAsync(path: string): Promise<string>Writing files
import { writeFile, writeFileAsync } from "ags/file"
function writeFile(path: string, content: string): void
function writeFileAsync(path: string, content: string): Promise<void>Monitoring files
If path is a directory it will be recursively monitored.
import { monitorFile } from "ags/file"
function monitorFile(
path: string,
callback: (file: string, event: Gio.FileMonitorEvent) => void,
): Gio.FileMonitorTimeouts and Intervals
import { interval, timeout, idle, createPoll } from "ags/time"You can use JavaScript native setTimeout or setInterval functions which return a GLib.Source instance. Alternatively you can use these functions provided by AGS, which return a Timer instance.
class Timer extends GObject.Object {
declare $signals: {
now(): void
cancelled(): void
}
cancel(): void
}Interval
Will immediately execute the function and every interval millisecond.
function interval(interval: number, callback?: () => void): TimerTimeout
Will execute the callback after timeout millisecond.
function timeout(timeout: number, callback?: () => void): TimerIdle
Executes callback whenever there are no higher priority events pending.
function idle(callback?: () => void): TimerExample:
const timer = interval(1000, () => {
console.log("optional callback")
})
timer.connect("now", () => {
console.log("tick")
})
timer.connect("cancelled", () => {
console.log("cancelled")
})
timer.cancel()createPoll
createPoll creates a signal that only polls when there is at least one subscriber.
function createPoll(
init: string,
interval: number,
exec: string | string[],
): Accessor<string>
function createPoll<T>(
init: T,
interval: number,
exec: string | string[],
transform: (stdout: string, prev: T) => T,
): Accessor<T>
function createPoll<T>(
init: T,
interval: number,
fn: (prev: T) => T | Promise<T>,
): Accessor<T>Example:
function Counter() {
const counter = createPoll(0, 1000, (prev) => prev + 1)
return <label label={counter((c) => c.toString())} />
}WARNING
Under the hood when passing a command as the third argument it uses execAsync which runs the given programs as is. They are not executed in a shell environment, they do not expand ENV variables like $HOME, and they do not handle logical operators like && and ||.
If you want bash, run them with bash.
createPoll("", 1000, "bash -c 'command $ENV_VAR && command'")Process functions
Import from ags/process
import { subprocess, exec, execAsync, createSubprocess } from "ags/process"Subprocess
You can start a subprocess and run callback functions whenever it outputs to stdout or stderr. The returned Process instance has an stdout and stderr signal.
class Process extends GObject.Object {
declare $signals: {
stdout(out: string): void
stderr(err: string): void
exit(code: number, signaled: boolean): void
}
kill(): void
write(str: string): void
async writeAsync(str: string): Promise<void>
}
function subprocess(args: {
cmd: string | string[]
out?: (stdout: string) => void
err?: (stderr: string) => void
}): Process
function subprocess(
cmd: string | string[],
onOut?: (stdout: string) => void,
onErr?: (stderr: string) => void,
): ProcessExample:
const proc = subprocess(
"some-command",
(out) => console.log(out), // optional
(err) => console.error(err), // optional
)
// or with signals
const proc = subprocess("some-command")
proc.connect("stdout", (_, out) => console.log(out))
proc.connect("stderr", (_, err) => console.error(err))Executing external commands and scripts
function exec(cmd: string | string[]): string
function execAsync(cmd: string | string[]): Promise<string>WARNING
You should generally avoid exec and use its async variant execAsync as the former will block IO, meaning the whole shell will freeze and will be unresponsive until it returns.
Example:
try {
const out = exec("/path/to/script")
console.log(out)
} catch (err) {
console.error(err)
}
execAsync(["bash", "-c", "/path/to/script.sh"])
.then((out) => console.log(out))
.catch((err) => console.error(err))WARNING
subprocess, exec, and execAsync executes the passed executable as is. They are not executed in a shell environment, they do not expand ENV variables like $HOME, and they do not handle logical operators like && and ||.
If you want bash, run them with bash.
exec(["bash", "-c", "command $ENV_VAR && command"])
exec("bash -c 'command $ENV_VAR' && command")createSubprocess
createSubprocess creates a signal that starts a subprocess when the first subscriber appears and kills the subprocess when number of subscribers drop to zero.
export function createSubprocess(
init: string,
exec: string | string[],
): Accessor<string>
export function createSubprocess<T>(
init: T,
exec: string | string[],
transform: (stdout: string, prev: T) => T,
): Accessor<T>Example:
function Log() {
const log = createSubprocess("", "journalctl -f")
return <label label={log} />
}Http requests
import { fetch, URL } from "ags/fetch"
const url = new URL("https://some-site.com/api")
url.searchParams.set("hello", "world")
const res = await fetch(url, {
method: "POST",
body: JSON.stringify({ hello: "world" }),
headers: {
"Content-Type": "application/json",
},
})
const json = await res.json()