import { avril, pledge, env, process, runtime, inspect, serve, serveFile, upgradeWebSocket, connect, listen, listenDatagram, Conn, Listener, DatagramConn, FileHandle, FsWatcher, SeekMode, errors, open, create, stat, lstat, readDir, watchFs, mkdir, remove, rename, copyFile, symlink, readLink, realPath, chmod, chown, lchown, utime, lutime, link, truncate, ChildProcess, ProcessError, OutputLimitError, ProcessTimeoutError, ProcessAbortError, run, runSync, spawn, addSignalListener, removeSignalListener, stdin, stdout, stderr, type TcpAddr, type UnixAddr, type UdpAddr, type StreamAddr, type Addr, type ServeInfo, type ServeHandler, type ServeModule, type HttpServer, type ProcessReason, type ProcessStatus, type ProcessOutput, type ProcessPromise, type ProcessOptions, type SpawnOptions, type RunSyncOptions, type ProcessTerminal, type ProcessStdio, type ExtraProcessStdio, type FileInfo, type DirEntry, type FsEvent, type FsEventKind, type WatchOptions, type OpenOptions, type Pledge, type GrantRestriction, } from "avril:std"; import * as sync from "avril:std/sync"; // @ts-expect-error Facade support types are private. import type { ClassStatics } from "avril:std"; const brand: symbol = avril; const branded: { readonly [avril]: true } = { [avril]: true }; const connectionName: string = Conn.name; const listenerArity: number = Listener.length; const reflected: Function = ChildProcess; const prototype: Conn = Conn.prototype; // @ts-expect-error Class prototype properties cannot be replaced. Conn.prototype = prototype; const restriction: GrantRestriction = { allow: [new URL("file:///tmp/")] }; const narrowed: Pledge = { read: restriction, net: false }; pledge(narrowed); // @ts-expect-error Authority categories use the capability vocabulary. pledge({ filesystem: false }); const variable: string | undefined = env.get("HOME"); const snapshot: Record = env.toObject(); const pid: number = process.pid; const args: readonly string[] = process.args; const os: "linux" | "macos" | "windows" = runtime.os; const arch: "x86_64" | "aarch64" = runtime.arch; const version: string = runtime.version; const v8: string = runtime.v8; const cwd: string = process.cwd(); const averages: [number, number, number] = process.loadavg(); const formatted: string = inspect(snapshot, { depth: null, colors: false }); // @ts-expect-error Frozen script arguments are not mutable. process.args.push("extra"); // @ts-expect-error Runtime metadata is readonly. runtime.os = "linux"; const tcpServer: HttpServer = serve((request, info) => { const port: number = info.remoteAddr.port; // @ts-expect-error TCP peer addresses have no Unix path. info.remoteAddr.path; return new Response(request.url + port); }); serve({ port: 0, onListen(addr) { const port: number = addr.port; } }, async () => new Response()); const unixServer: HttpServer = serve({ path: "/tmp/http.sock", onListen(addr) { const path: string | null = addr.path; }, }, (request, info) => { const path: string | null = info.remoteAddr.path; // @ts-expect-error Unix peer addresses have no TCP port. info.remoteAddr.port; return new Response(path); }); // @ts-expect-error A Unix listener cannot also have a TCP port. serve({ path: "/tmp/http.sock", port: 80 }, () => new Response()); // @ts-expect-error A handler must return a Response. serve(() => "not a response"); const handler: ServeHandler = (request, info: ServeInfo) => new Response(info.remoteAddr.transport); const module: ServeModule = { fetch: handler }; const shutdown: Promise = unixServer.shutdown(); const upgraded: { socket: WebSocket; response: Response } = upgradeWebSocket(new Request("http://localhost/")); const tcp = await connect({ port: 80 }); const tcpAddress: TcpAddr = tcp.remoteAddr; const unix = await connect({ transport: "unix", path: "/tmp/socket" }); const unixAddress: UnixAddr = unix.remoteAddr; const tcpListener = listen({ port: 0 }); const accepted: Conn = await tcpListener.accept(); const unixListener = listen({ transport: "unix", path: "/tmp/socket" }); const unixAccepted: Conn = await unixListener.accept(); const tcpConnections: AsyncIterable> = tcpListener; const unixConnections: AsyncIterable> = unixListener; const finishedWrite: Promise = tcp.closeWrite(); // @ts-expect-error closeWrite has no result. const nullShutdown: Promise = tcp.closeWrite(); // @ts-expect-error Unix connections cannot be used as TCP connections. const wrongConnection: Conn = unix; // @ts-expect-error Stream listeners do not use UDP. listen({ transport: "udp", port: 0 }); // @ts-expect-error TCP connect requires a port. connect({ hostname: "localhost" }); const datagram = listenDatagram({ port: 0 }); const received: [Uint8Array, UdpAddr] = await datagram.receive(); const packets: AsyncIterable<[Uint8Array, UdpAddr]> = datagram; const streamAddress: StreamAddr = unixAddress; const address: Addr = received[1]; const options: OpenOptions = { read: true, write: true }; const file: FileHandle = await open(new URL("file:///data"), options); const bytes = new Uint8Array(new SharedArrayBuffer(8)); const count: number | null = await file.read(bytes); const written: number = await file.writev([bytes] as const); const writtenSync: number = file.writevSync([bytes] as const); const seek: Promise = file.seek(0, SeekMode.Start); const metadata: FileInfo = await file.stat(); const entries: AsyncIterable = readDir("."); const watcherOptions: WatchOptions = { recursive: true, signal: new AbortController().signal }; const watcher: FsWatcher = watchFs([".", new URL("file:///tmp")], watcherOptions); const events: AsyncIterable = watcher; const kind: FsEventKind = "rescan"; const disposable: Disposable = file; const watchDisposable: Disposable = watcher; const response: Promise = serveFile(new Request("http://localhost/"), file, { consume: false }); // @ts-expect-error Seek modes are a closed set. file.seek(0, 3); // @ts-expect-error Reads require byte views. file.read(new Uint16Array()); // @ts-expect-error writev requires an array, not an arbitrary iterator. file.writev(new Set([bytes])); const syncFile: FileHandle = sync.open("data"); const syncType: sync.FileHandle = file; const syncOptions: sync.OpenOptions = options; const syncMetadata: sync.FileInfo = sync.stat("data"); const syncEntries: Iterable = sync.readDir("."); const syncErrors: typeof errors = sync.errors; const syncHandle: typeof FileHandle = sync.FileHandle; const syncSeek: 2 = sync.SeekMode.End; const readCount: number | null = sync.stdin.read(bytes); const writeCount: number = sync.stdout.write(bytes); const errorCount: number = sync.stderr.write(bytes); // @ts-expect-error Sync operations do not return promises. const notAsync: Promise = sync.stat("data"); // @ts-expect-error Sync paths are strings or URLs. sync.open(42); const raw: ProcessPromise = run("tool"); const text: ProcessPromise = run("tool", { encoding: "utf-8" }); const positional: ProcessPromise = run("tool", ["arg"], { check: false }); const positionalText: ProcessPromise = run("tool", undefined, { encoding: "utf-8" }); const rawOutput: ProcessOutput = await raw; const textOutput: ProcessOutput = await text; const outputBytes: Uint8Array | null = rawOutput.stdout; const outputText: string | null = textOutput.stdout; const shortcutBytes: Promise = text.bytes(); const shortcutText: Promise = raw.text(); const json: Promise = text.json(); const lines: AsyncIterableIterator = text.lines(); const syncRaw: ProcessOutput = runSync("tool"); const syncText: ProcessOutput = runSync("tool", { encoding: "utf-8" }); const syncPositional: ProcessOutput = runSync("tool", ["arg"]); const syncPositionalText: ProcessOutput = runSync("tool", ["arg"], { encoding: "utf-8" }); const child: ChildProcess = spawn("tool"); const textChild: ChildProcess = spawn("tool", { encoding: "utf-8" }); const childPositional: ChildProcess = spawn("tool", ["arg"]); const textChildPositional: ChildProcess = spawn("tool", undefined, { encoding: "utf-8" }); const childOutput: ProcessOutput = await textChild.output(); const status: ProcessStatus = await child.status; const reason: ProcessReason | null = status.reason; const terminal: ProcessTerminal | null = child.terminal; const childDisposable: AsyncDisposable = child; const processOptions: ProcessOptions = { stdin: { handle: file }, input: new ReadableStream() }; const spawnOptions: SpawnOptions = { terminal: { columns: 80 }, extraStdio: { 3: { pipe: "child-to-parent" } } }; const syncRunOptions: RunSyncOptions = { input: bytes }; const stdioOption: ProcessStdio = { file: "output", mode: "append" }; const extra: ExtraProcessStdio = { handle: file, direction: "child-to-parent" }; // @ts-expect-error Raw output is bytes, not decoded text. const wrongText: string | null = rawOutput.stdout; // @ts-expect-error Decoded output is text, not bytes. const wrongBytes: Uint8Array | null = textOutput.stderr; // @ts-expect-error Positional args cannot be repeated in options. run("tool", ["arg"], { args: ["again"] }); // @ts-expect-error Sync runs do not accept streaming input. runSync("tool", { input: new ReadableStream() }); // @ts-expect-error Sync runs do not accept an AbortSignal. runSync("tool", { signal: new AbortController().signal }); // @ts-expect-error Spawn results are not promises. const notPromise: Promise = child; // @ts-expect-error Native failure reasons have a closed vocabulary. const invalidReason: ProcessReason = "other"; const failure = new ProcessError("failed", rawOutput, new Error()); const limited = new OutputLimitError(textOutput); const timedOut = new ProcessTimeoutError(rawOutput); const aborted = new ProcessAbortError(null, "cancel"); const parent: ProcessError = limited; const error: Error = failure; const isProcessError: boolean = ProcessError.isError(failure); const isOutputLimitError: boolean = OutputLimitError.isError(limited); const isProcessTimeoutError: boolean = ProcessTimeoutError.isError(timedOut); const isProcessAbortError: boolean = ProcessAbortError.isError(aborted); class CustomProcessError extends ProcessError {} declare const unknownValue: unknown; if (unknownValue instanceof Conn) { const addr: StreamAddr = unknownValue.remoteAddr; // @ts-expect-error instanceof alone cannot establish TCP transport. const tcpOnly: Conn = unknownValue; } if (unknownValue instanceof Listener) { const conn: Conn = await unknownValue.accept(); } if (unknownValue instanceof DatagramConn) { const addr: UdpAddr = unknownValue.addr; } if (unknownValue instanceof FileHandle) { const result: FileInfo = await unknownValue.stat(); } if (unknownValue instanceof sync.FileHandle) { const handle: FileHandle = unknownValue; } if (unknownValue instanceof FsWatcher) { const iterable: AsyncIterable = unknownValue; } if (unknownValue instanceof ChildProcess) { const pid: number = unknownValue.pid; } if (unknownValue instanceof ProcessError) { const error: Error = unknownValue; const output: ProcessOutput | null = unknownValue.result; } if (unknownValue instanceof OutputLimitError) { const parent: ProcessError = unknownValue; const error: Error = unknownValue; } if (unknownValue instanceof ProcessTimeoutError) { const parent: ProcessError = unknownValue; } if (unknownValue instanceof ProcessAbortError) { const parent: ProcessError = unknownValue; } // @ts-expect-error Connections cannot be constructed. new Conn(); // @ts-expect-error Listeners cannot be constructed. new Listener(); // @ts-expect-error Datagram sockets cannot be constructed. new DatagramConn(); // @ts-expect-error File handles cannot be constructed. new FileHandle(); // @ts-expect-error Watchers cannot be constructed. new FsWatcher(); // @ts-expect-error Child processes must be spawned. new ChildProcess(); // @ts-expect-error ProcessError's message is required. new ProcessError(); // @ts-expect-error OutputLimitError requires a result. new OutputLimitError(); const inputStream: ReadableStream = stdin; const outputStream: WritableStream = stdout; const errorStream: WritableStream = stderr; addSignalListener("SIGTERM", () => {}); removeSignalListener("SIGTERM", () => {}); // @ts-expect-error Signal listeners take callbacks. addSignalListener("SIGTERM", 42); // Keep the ordinary filesystem operations represented alongside their sync siblings. const created: Promise = create("file"); const stats: Promise[] = [stat("."), lstat(".")]; const changes: Promise[] = [ mkdir("dir"), remove("dir"), rename("a", "b"), copyFile("a", "b"), symlink("target", "link"), chmod("file", 0o600), chown("file", null, null), lchown("link", null, null), utime("file", new Date(), 0), lutime("link", 0, 0), link("a", "b"), truncate("file"), ]; const paths: Promise[] = [readLink("link"), realPath(".")]; const syncCreated: FileHandle = sync.create("file"); const syncStats: FileInfo[] = [sync.stat("."), sync.lstat(".")]; const syncChanges: void[] = [ sync.mkdir("dir"), sync.remove("dir"), sync.rename("a", "b"), sync.copyFile("a", "b"), sync.symlink("target", "link"), sync.chmod("file", 0o600), sync.chown("file", null, null), sync.lchown("link", null, null), sync.utime("file", new Date(), 0), sync.lutime("link", 0, 0), sync.link("a", "b"), sync.truncate("file"), ]; const syncPaths: string[] = [sync.readLink("link"), sync.realPath(".")];