The Velt standard library
The standard library is written in Velt and ships with the toolchain. A module is imported as
velt/<module>, the path of its folder in the standard library:
import { readFile, writeFile } from "velt/fs";
import { Deque } from "velt/collections";
await writeFile("notes.txt", "hello");
const queue = new Deque<string>();
queue.pushBack(await readFile("notes.txt"));
console.log(queue.length);The prelude (strings, arrays, Map, Math, JSON, Error, promises, …) is
in scope everywhere without an import, and so are Node's web globals: fetch,
Request, Response, Headers, Blob, File, FormData, AbortController, AbortSignal,
URL, URLSearchParams, Set, RegExp, Symbol, TextEncoder,
TextDecoder, btoa, atob, DOMException, structuredClone, ArrayBuffer, DataView,
Uint8Array and the other typed arrays, and
ReadableStream. velt doc --std generates HTML API documentation from
the sources; the API pages here are generated the same way.
Importing a module
-
An area or a module is a folder, and its import path is that folder:
velt/fs,velt/net,velt/net/http,velt/encoding/json. Each has one public API, the names itsindex.vltexports. The other files of a module are its internals, and importing one is an error that names the module to import instead:tsdoes not compileimport { Deque } from "velt/collections/deque";Texterror: `velt/collections/deque` is internal to `velt/collections` = note: import what you need from "velt/collections", the module's public API -
The prelude is never imported. Its names are in scope in every module;
import … from "velt/prelude"is an error. The same goes forvelt/lang/…, which implements the language: what a program uses of it is global (Symbol,Proxy,Uint8Array, …) or syntax (import.meta).
Conventions
- Errors are thrown classes extending the prelude
Error { message }. Catch them withtry { … } catch (e) { e.message };eis the union of the error classes the calls can throw, narrowed withinstanceof. Each module has its own error class (UrlError,CsvError, …). Messages start with a capital letter (Invalid URL: …);IoErrormessages are lowercase, as in Node (ENOENT: no such file or directory, open 'x',handle is closed). An error that escapes the program printsUncaught <Class>: <message> at <file>:<line>:<col>, naming the error's actual class and, for an error thrown inside the standard library, the line of your code that called it. - I/O errors are
IoError { code, message }fromvelt/io.codeis a Node-style name:"ENOENT","EACCES","ECONNREFUSED","EOF", … A failed file-system call has Node's message:ENOENT: no such file or directory, open 'data.txt'. - Strings are sequences of UTF-16 code units, as in JS: lengths and positions (
slice,indexOf, regex match offsets, CSV and CLI column widths) count code units. Their text is stored and written as UTF-8;Buffer.byteLength(s)is that size. - Async functions return promises that start at once, like JS (a direct
awaitcosts nothing). A promise that is neither awaited nor spawned is a compile error.*Syncvariants block the calling thread. - Handles: some modules return handle structs (
TcpStream,FileReader,ChildProcess, …) that you can pass around and capture freely and release withclose()(closing again does nothing). Planned: they become disposable classes withusingsupport.
Modules
Each module has a page at the same path as its import (velt/net/http is
/docs/std/net/http/); a module with several parts has a page for each
below its own. The catalog groups them by what they are for.
| Module | Pages |
|---|---|
| cli | command-line programs: arguments, subcommands, --help, exit codes |
| collections | BTreeMap · ConcurrentMap · Deque · PriorityQueue · Set · SortedMap |
| compress | gzip, zlib, DEFLATE, Brotli |
| crypto | hashing, HMAC, secure random values |
| db | typed rows from any source |
| dev | the graceful stop under velt dev |
| encoding | base64, hex, UTF-8 · csv · json |
| fs | files and directories · file streams |
| generate | what source generators are written with |
| hash | stable, non-cryptographic hashing |
| io | IoError, readers and writers · streams (ReadableStream, global) |
| jsx | TSX rendering · attrs · jsx-runtime · generic/jsx-runtime |
| math | integer helpers · BigInt |
| mem | needsDrop, for containers · arenas |
| native | the Velt side of packages with native code |
| net | TCP and TLS · dns · http (fetch, global) · http/h2 · udp · url · websocket (the client) |
| os | platform facts |
| package | the type of package.vlt |
| path | paths |
| process | arguments, environment, exit · standard input · child (child processes) |
| random | a fast per-thread generator · uuid |
| reflect | what an any holds at run time |
| simd | the vector types and their methods |
| sync | Atomic<T> (in the prelude), Backoff, VersionLatch · channels · epoch (reclamation) |
| task | cancellation, timeouts, task scopes |
| test | the runner velt test builds into test programs · http (matchers for a Response) |
| text | regular expressions · StringBuilder · HTML escaping |
| time | DateTime and Duration · timers |
The prelude's globals have pages of their own too: Symbol and
typed arrays, ArrayBuffer and DataView.
Packages, not std
The standard library is the core every program can count on. Servers and database drivers are
libraries, so they are packages, written on public std APIs only:
http-server (serve, with web-standard Request and Response
handlers), sqlite, postgres and
redis. A program imports a package by its name
(import { serve } from "http-server") once package.vlt lists it in dependencies. std keeps
what any of them builds on: fetch and the web types, velt/net/http/h2,
velt/db, velt/dev, velt/native and
the WebSocket client.
Runtime-backed and pure modules
Every module is Velt source. Some bind runtime functions (velt_rt_*, implemented in Rust) for
what Velt can't do on its own:
| Module | Runtime use |
|---|---|
velt/fs, velt/net | the file system, TCP and TLS streams (TLS through rustls) |
velt/net/http | TCP and TLS connections, which the runtime pools between requests; HTTP/1.1, HTTP/2 (velt/net/http/h2) and body decoding (velt/compress) are Velt |
velt/net/websocket | none of its own: the protocol is Velt on velt/net streams (the runtime only masks bytes, checks UTF-8 and draws masking keys) |
velt/process, velt/os | arguments, environment, working directory, standard input, platform facts |
velt/process/child | process spawning and pipes |
velt/net/udp, velt/net/dns | sockets and the system resolver |
velt/sync, velt/task | channel queues, abort signals and task groups |
velt/text | Rust's regex engine; escapeHtml and StringBuilder are runtime passes over bytes |
velt/math | arbitrary-precision integers (dashu-int) |
velt/crypto, velt/random/uuid | only the operating system's secure random generator; hashing, HMAC and formatting are Velt (on the CPU's SHA instructions through velt/simd where it has them) |
velt/random | a per-thread wyrand generator |
velt/time | only the local UTC offset; calendar math, parsing and formatting are Velt |
velt/hash | FNV-1a over a string's or array's bytes, without a copy |
Pure Velt: velt/path, velt/mem, velt/collections, velt/encoding (with
velt/encoding/csv and velt/encoding/json), velt/cli, velt/jsx, velt/generate,
velt/net/http/h2, velt/net/url and the timers of velt/time (built on sleep, spawn and
velt/task signals); some use only the runtime's UTF-8 conversions and error-code names.
WebAssembly
On the WebAssembly targets the language and the pure modules work as on native targets, and
velt/fs uses the WASI file system. TCP, child processes and the native code of the database
packages are not available; fetch links but rejects with IoError ENOTSUP (no network)
(WebAssembly).