All functions available in Covenant's standard library, organized by module. Each function is called using its fully-qualified snippet ID and requires its declared effect.
- Console
- HTTP
- Filesystem
- Crypto
- Database
- Process
- OS/Environment
- Path
- JSON
- Timers
- URL
- Storage: Key-Value
- Storage: Document
Output to the runtime console. All functions accept a primary message and an optional list of additional values.
Effect: console
Platforms: deno, browser, node, wasi
| Function | Parameters | Returns |
|---|---|---|
console.println |
msg: String, values: List<String> (optional) |
Unit |
console.info |
msg: String, values: List<String> (optional) |
Unit |
console.debug |
msg: String, values: List<String> (optional) |
Unit |
console.warn |
msg: String, values: List<String> (optional) |
Unit |
console.error |
msg: String, values: List<String> (optional) |
Unit |
step id="s1" kind="call"
fn="console.println"
arg name="msg" lit="Hello, world!"
as="_"
end
step id="s2" kind="call"
fn="console.warn"
arg name="msg" lit="Connection pool running low"
arg name="values" from="pool_stats"
as="_"
end
step id="s3" kind="call"
fn="console.error"
arg name="msg" lit="Failed to connect"
arg name="values" from="error_details"
as="_"
end
HTTP client operations using the platform's native fetch API.
Effect: network
Platforms: deno, browser, node
struct name="Response"
field name="status" type="Int"
field name="body" type="String"
field name="headers" type="Map<String,String>"
end
struct name="HttpError"
field name="message" type="String"
field name="status" type="Int" optional
end
| Function | Parameters | Returns |
|---|---|---|
http.get |
url: String, headers: Map<String,String> (optional), timeout: Int (optional) |
Response | HttpError |
http.post |
url: String, body: String, headers: Map<String,String> (optional), content_type: String (optional), timeout: Int (optional) |
Response | HttpError |
http.put |
url: String, body: String, headers: Map<String,String> (optional), content_type: String (optional), timeout: Int (optional) |
Response | HttpError |
http.delete |
url: String, headers: Map<String,String> (optional), timeout: Int (optional) |
Response | HttpError |
http.request |
url: String, method: String, body: String (optional), headers: Map<String,String> (optional), content_type: String (optional), timeout: Int (optional) |
Response | HttpError |
step id="s1" kind="call"
fn="http.get"
arg name="url" lit="https://api.example.com/users"
arg name="headers" from="auth_headers"
arg name="timeout" lit=5000
as="response"
end
step id="s2" kind="call"
fn="http.post"
arg name="url" lit="https://api.example.com/users"
arg name="body" from="payload"
arg name="content_type" lit="application/json"
as="result"
end
step id="s3" kind="call"
fn="http.request"
arg name="url" lit="https://api.example.com/resource"
arg name="method" lit="PATCH"
arg name="body" from="patch_data"
arg name="headers" from="headers"
arg name="content_type" lit="application/json"
arg name="timeout" lit=10000
as="patch_result"
end
Read, write, and manage files and directories on the local filesystem.
Effect: filesystem
Platforms: deno
Deno permission: --allow-read, --allow-write
struct name="FileStat"
field name="size" type="Int"
field name="is_file" type="Bool"
field name="is_directory" type="Bool"
field name="modified" type="DateTime" optional
end
struct name="DirEntry"
field name="name" type="String"
field name="is_file" type="Bool"
field name="is_directory" type="Bool"
end
struct name="FileHandle"
field name="id" type="Int"
field name="path" type="String"
end
struct name="IoError"
field name="message" type="String"
field name="code" type="String"
end
| Function | Parameters | Returns | Description |
|---|---|---|---|
fs.read_file |
path: String |
String | IoError |
Read entire file as text |
fs.write_file |
path: String, content: String |
Unit | IoError |
Write text to file |
fs.write_bytes |
path: String, content: Bytes |
Unit | IoError |
Write binary data to file |
fs.remove |
path: String |
Unit | IoError |
Delete file or directory |
fs.stat |
path: String |
FileStat | IoError |
Get file/directory metadata |
fs.read_dir |
path: String |
List<DirEntry> | IoError |
List directory contents |
fs.exists |
path: String |
Bool |
Check if path exists |
fs.mkdir |
path: String, recursive: Bool (optional) |
Unit | IoError |
Create directory |
fs.copy |
src: String, dest: String |
Unit | IoError |
Copy file |
fs.rename |
src: String, dest: String |
Unit | IoError |
Rename or move file |
fs.chmod |
path: String, mode: Int |
Unit | IoError |
Set file permissions |
fs.open |
path: String, mode: String |
FileHandle | IoError |
Open file for streaming I/O |
fs.read_bytes |
handle: FileHandle, offset: Int (optional), length: Int (optional) |
Bytes | IoError |
Read bytes from open file |
fs.close |
handle: FileHandle |
Unit |
Close an open file handle |
step id="s1" kind="call"
fn="fs.read_file"
arg name="path" lit="./config.json"
as="contents"
end
step id="s2" kind="call"
fn="fs.write_file"
arg name="path" lit="./output.txt"
arg name="content" from="data"
as="_"
end
step id="s1" kind="call"
fn="fs.mkdir"
arg name="path" lit="./output/reports"
arg name="recursive" lit=true
as="_"
end
step id="s2" kind="call"
fn="fs.read_dir"
arg name="path" lit="./output"
as="entries"
end
For reading large files in chunks rather than loading the entire file into memory:
step id="s1" kind="call"
fn="fs.open"
arg name="path" lit="./large-file.bin"
arg name="mode" lit="read"
as="handle"
end
step id="s2" kind="call"
fn="fs.read_bytes"
arg name="handle" from="handle"
arg name="offset" lit=0
arg name="length" lit=4096
as="chunk"
end
step id="s3" kind="call"
fn="fs.close"
arg name="handle" from="handle"
as="_"
end
step id="s1" kind="call"
fn="fs.exists"
arg name="path" lit="./config.json"
as="config_exists"
end
step id="s2" kind="call"
fn="fs.copy"
arg name="src" lit="./config.json"
arg name="dest" lit="./config.backup.json"
as="_"
end
step id="s3" kind="call"
fn="fs.chmod"
arg name="path" lit="./script.sh"
arg name="mode" lit=755
as="_"
end
Cryptographic hashing and random number generation.
Platforms: deno, node
| Function | Parameters | Returns | Effect |
|---|---|---|---|
crypto.sha256 |
input: String |
String |
(pure) |
crypto.random_bytes |
length: Int |
Bytes |
random |
step id="s1" kind="call"
fn="crypto.sha256"
arg name="input" lit="hello"
as="hash"
end
step id="s2" kind="call"
fn="crypto.random_bytes"
arg name="length" lit=32
as="token"
end
Connect to and query external SQL databases.
Effect: database
Platforms: deno, node
| Function | Parameters | Returns |
|---|---|---|
db.connect |
url: String |
Connection | DbError |
db.query |
conn: Connection, sql: String, params: List<String> (optional) |
Rows | DbError |
step id="s1" kind="call"
fn="db.connect"
arg name="url" lit="env:DATABASE_URL"
as="conn"
end
step id="s2" kind="call"
fn="db.query"
arg name="conn" from="conn"
arg name="sql" lit="SELECT * FROM users WHERE active = true"
as="rows"
end
Use the params argument for safe parameter binding (prevents SQL injection):
step id="s1" kind="call"
fn="db.query"
arg name="conn" from="conn"
arg name="sql" lit="SELECT * FROM users WHERE age > $1 AND status = $2"
arg name="params" from="query_params"
as="rows"
end
For complex queries with compile-time type checking, prefer the SQL dialect query syntax:
step id="s1" kind="query"
dialect="postgres"
target="app_db"
body
SELECT id, name FROM users WHERE created_at > :cutoff AND status = :status
end
params
param name="cutoff" from="cutoff_date"
param name="status" lit="active"
end
returns collection of="User"
as="recent_users"
end
Execute external programs and manage subprocesses.
Effect: process
Platforms: deno
Deno permission: --allow-run
struct name="ProcessResult"
field name="exit_code" type="Int"
field name="stdout" type="String"
field name="stderr" type="String"
end
struct name="ProcessHandle"
field name="pid" type="Int"
end
struct name="ProcessError"
field name="message" type="String"
field name="code" type="String"
end
| Function | Parameters | Returns | Description |
|---|---|---|---|
process.exec |
command: String, args: List<String> (optional), cwd: String (optional), env: Map<String,String> (optional), timeout: Int (optional) |
ProcessResult | ProcessError |
Run command and wait for completion |
process.spawn |
command: String, args: List<String> (optional), cwd: String (optional), env: Map<String,String> (optional) |
ProcessHandle | ProcessError |
Start a background process |
process.kill |
handle: ProcessHandle |
Unit |
Terminate a spawned process |
process.wait |
handle: ProcessHandle |
ProcessResult | ProcessError |
Wait for a spawned process to finish |
step id="s1" kind="call"
fn="process.exec"
arg name="command" lit="git"
arg name="args" lit=["status", "--porcelain"]
arg name="cwd" lit="/project"
arg name="timeout" lit=30000
as="result"
end
step id="s2" kind="bind"
field="stdout" of="result"
as="git_status"
end
step id="s1" kind="call"
fn="process.spawn"
arg name="command" lit="node"
arg name="args" lit=["server.js"]
arg name="env" from="server_env"
as="server"
end
// ... do other work ...
step id="s2" kind="call"
fn="process.kill"
arg name="handle" from="server"
as="_"
end
Access operating system information and environment variables.
Effect: os
Platforms: deno, node
Deno permission: --allow-env
| Function | Parameters | Returns | Description |
|---|---|---|---|
os.env_get |
name: String |
String? |
Get environment variable (none if unset) |
os.env_set |
name: String, value: String |
Unit |
Set environment variable |
os.platform |
(none) | String |
OS name: "linux", "darwin", "windows" |
os.arch |
(none) | String |
CPU architecture: "x86_64", "aarch64" |
step id="s1" kind="call"
fn="os.env_get"
arg name="name" lit="DATABASE_URL"
as="db_url"
end
step id="s2" kind="call"
fn="os.env_set"
arg name="name" lit="NODE_ENV"
arg name="value" lit="production"
as="_"
end
step id="s3" kind="call"
fn="os.platform"
as="platform"
end
step id="s4" kind="call"
fn="os.arch"
as="arch"
end
File path manipulation utilities. Most functions are pure (no side effects). path.resolve requires the os effect to access the current working directory.
Platforms: deno, browser, node, wasi
| Function | Parameters | Returns | Effect |
|---|---|---|---|
path.join |
base: String, segment: String |
String |
(pure) |
path.resolve |
path: String |
String |
os |
path.dirname |
path: String |
String |
(pure) |
path.basename |
path: String |
String |
(pure) |
path.extname |
path: String |
String |
(pure) |
path.is_absolute |
path: String |
Bool |
(pure) |
Note: path.join takes exactly 2 segments. For multi-segment joins, chain calls:
step id="s1" kind="call"
fn="path.join"
arg name="base" lit="/home/user"
arg name="segment" lit="documents"
as="p1"
end
step id="s2" kind="call"
fn="path.join"
arg name="base" from="p1"
arg name="segment" lit="report.txt"
as="full_path"
end
step id="s3" kind="call"
fn="path.dirname"
arg name="path" from="full_path"
as="dir"
end
step id="s4" kind="call"
fn="path.extname"
arg name="path" from="full_path"
as="ext"
end
step id="s5" kind="call"
fn="path.is_absolute"
arg name="path" from="full_path"
as="is_abs"
end
Requires os effect since it accesses the current working directory:
effects
effect os
end
body
step id="s1" kind="call"
fn="path.resolve"
arg name="path" lit="./relative/file.txt"
as="absolute_path"
end
end
Parse and serialize JSON data. All functions are pure (no side effects).
Platforms: deno, browser, node, wasi
enum name="Json"
variant name="Null"
variant name="Bool"
field name="value" type="Bool"
end
variant name="Number"
field name="value" type="Float"
end
variant name="String"
field name="value" type="String"
end
variant name="Array"
field name="items" type="Json[]"
end
variant name="Object"
field name="fields" type="Map<String, Json>"
end
end
enum name="JsonError"
variant name="ParseError"
field name="message" type="String"
field name="line" type="Int"
field name="column" type="Int"
end
variant name="InvalidType"
field name="expected" type="String"
field name="actual" type="String"
end
end
| Function | Parameters | Returns | Description |
|---|---|---|---|
json.parse |
input: String |
Json | JsonError |
Parse JSON string into Json type |
json.stringify |
value: Json |
String |
Serialize Json to compact JSON string |
json.format |
value: Json, indent: String (optional) |
String |
Pretty-print JSON with indentation (default 2 spaces) |
json.is_valid |
input: String |
Bool |
Check if string is valid JSON |
| Function | Parameters | Returns |
|---|---|---|
json.is_object |
value: Json |
Bool |
json.is_array |
value: Json |
Bool |
json.is_string |
value: Json |
Bool |
json.is_number |
value: Json |
Bool |
json.is_bool |
value: Json |
Bool |
json.is_null |
value: Json |
Bool |
| Function | Parameters | Returns | Description |
|---|---|---|---|
json.as_string |
value: Json |
String? |
Extract string value (returns none for other types) |
json.as_number |
value: Json |
Float? |
Extract numeric value (returns none for other types) |
json.as_bool |
value: Json |
Bool? |
Extract boolean value (returns none for other types) |
json.get_field |
obj: Json, key: String |
Json? |
Extract field from object (returns none if not an object or key missing) |
json.get_index |
arr: Json, index: Int |
Json? |
Extract element from array (returns none if not an array or out of bounds) |
body
(* Parse JSON string *)
step id="s1" kind="call"
fn="json.parse"
arg name="input" lit="{\"name\":\"Alice\",\"age\":30}"
as="result"
end
(* Extract name field *)
step id="s2" kind="call"
fn="json.get_field"
arg name="obj" from="result"
arg name="key" lit="name"
as="name_field"
end
(* Convert to string *)
step id="s3" kind="call"
fn="json.as_string"
arg name="value" from="name_field"
as="name"
end
(* name is now "Alice" *)
end
body
(* Build JSON object using variant construction *)
step id="s1" kind="construct"
variant type="Json::Object"
field name="fields" map
entry key="status" value variant type="Json::String"
field name="value" lit="success"
end
entry key="code" value variant type="Json::Number"
field name="value" lit=200.0
end
end
end
as="json_obj"
end
(* Serialize to string *)
step id="s2" kind="call"
fn="json.stringify"
arg name="value" from="json_obj"
as="json_str"
end
(* json_str is now "{\"status\":\"success\",\"code\":200}" *)
end
body
(* Parse compact JSON *)
step id="s1" kind="call"
fn="json.parse"
arg name="input" lit="{\"a\":1,\"b\":2}"
as="parsed"
end
(* Format with 2-space indent *)
step id="s2" kind="call"
fn="json.format"
arg name="value" from="parsed"
arg name="indent" lit=" "
as="formatted"
end
(* formatted is now:
{
"a": 1,
"b": 2
}
*)
end
body
step id="s1" kind="call"
fn="json.parse"
arg name="input" from="user_input"
as="result"
end
step id="s2" kind="match"
on="result"
case variant type="Json"
(* Successfully parsed JSON *)
step id="s2a" kind="call"
fn="process_json"
arg name="data" from="result"
as="_"
end
end
case variant type="JsonError::ParseError" bindings=("msg", "line", "col")
(* Handle parse error *)
step id="s2b" kind="call"
fn="console.error"
arg name="msg" from="msg"
as="_"
end
end
as="_"
end
end
Delay execution. For timeout behavior on concurrent operations, use the timeout attribute on parallel blocks instead.
Effect: timers
Platforms: deno, browser, node
| Function | Parameters | Returns | Description |
|---|---|---|---|
timers.delay |
ms: Int |
Unit |
Pause execution for N milliseconds |
step id="s1" kind="call"
fn="console.println"
arg name="msg" lit="Starting..."
as="_"
end
step id="s2" kind="call"
fn="timers.delay"
arg name="ms" lit=2000
as="_"
end
step id="s3" kind="call"
fn="console.println"
arg name="msg" lit="2 seconds later"
as="_"
end
For repeated delays, use an explicit loop with timers.delay inside. For concurrent timeout behavior, use structured concurrency:
step id="s1" kind="parallel"
timeout=5s
on_timeout="cancel"
branch id="b1"
step id="b1.1" kind="call"
fn="http.get"
arg name="url" lit="https://slow-api.example.com/data"
as="response"
end
end
as="result"
end
URL parsing and formatting utilities.
Platforms: deno, browser, node, wasi
struct name="Url"
field name="protocol" type="String"
field name="host" type="String"
field name="port" type="Int" optional
field name="pathname" type="String"
field name="search" type="String" optional
field name="hash" type="String" optional
end
struct name="UrlError"
field name="message" type="String"
end
| Function | Parameters | Returns | Effect |
|---|---|---|---|
url.parse |
raw: String |
Url | UrlError |
(pure) |
url.format |
url: Url |
String |
(pure) |
url.resolve |
base: String, relative: String |
String |
(pure) |
step id="s1" kind="call"
fn="url.parse"
arg name="raw" lit="https://api.example.com:8080/v2/users?active=true#top"
as="parsed"
end
step id="s2" kind="bind"
field="host" of="parsed"
as="api_host"
end
step id="s3" kind="bind"
field="pathname" of="parsed"
as="api_path"
end
step id="s4" kind="call"
fn="url.resolve"
arg name="base" lit="https://example.com/api/v1/"
arg name="relative" lit="../v2/users"
as="resolved"
end
step id="s5" kind="call"
fn="url.format"
arg name="url" from="parsed"
as="url_string"
end
Simple key-value storage that works across all platforms.
Effect: std.storage
Platforms: deno, browser, node, wasi
Platform backends:
- Deno: Deno KV (built-in)
- Browser: localStorage
- Node.js: File-based storage (
~/.covenant-storage/kv/) - WASI: Preopened directory
| Function | Parameters | Returns | Description |
|---|---|---|---|
std.storage.kv.set |
key: String, value: String |
Unit |
Store a value |
std.storage.kv.get |
key: String |
String? |
Retrieve a value (none if missing) |
std.storage.kv.delete |
key: String |
Unit |
Delete a value |
std.storage.kv.has |
key: String |
Bool |
Check if key exists |
std.storage.kv.list |
prefix: String |
String[] |
List keys matching prefix |
std.storage.kv.clear |
prefix: String (optional) |
Unit |
Clear all keys or by prefix |
step id="s1" kind="call"
fn="std.storage.kv.set"
arg name="key" lit="user:theme"
arg name="value" lit="dark"
as="_"
end
step id="s2" kind="call"
fn="std.storage.kv.get"
arg name="key" lit="user:theme"
as="theme"
end
step id="s3" kind="call"
fn="std.storage.kv.has"
arg name="key" lit="user:theme"
as="exists"
end
step id="s4" kind="call"
fn="std.storage.kv.list"
arg name="prefix" lit="user:"
as="user_keys"
end
Document storage with queries, supporting structured data across all platforms.
Effect: std.storage
Platforms: deno, browser, node, wasi
Platform backends:
- Deno: Deno KV (structured keys)
- Browser: IndexedDB
- Node.js: SQLite (better-sqlite3)
- WASI: Embedded database
struct name="Document"
field name="id" type="String"
field name="data" type="Json"
field name="created_at" type="DateTime"
field name="updated_at" type="DateTime"
end
struct name="QueryResult"
field name="documents" type="Document[]"
field name="total" type="Int"
end
| Function | Parameters | Returns | Description |
|---|---|---|---|
std.storage.doc.put |
collection: String, id: String, data: Json |
Document |
Insert or update a document |
std.storage.doc.get |
collection: String, id: String |
Document? |
Get document by ID |
std.storage.doc.delete |
collection: String, id: String |
Bool |
Delete document (true if existed) |
std.storage.doc.query |
collection: String, filter: Json?, order_by: String?, order_dir: String?, limit: Int?, offset: Int? |
QueryResult |
Query with JSON filter |
std.storage.doc.count |
collection: String, filter: Json? |
Int |
Count matching documents |
std.storage.doc.create_index |
collection: String, field: String |
Unit |
Create index on a field |
step id="s1" kind="call"
fn="std.storage.doc.put"
arg name="collection" lit="users"
arg name="id" lit="user123"
arg name="data" from="user_json"
as="doc"
end
step id="s2" kind="call"
fn="std.storage.doc.get"
arg name="collection" lit="users"
arg name="id" lit="user123"
as="user"
end
step id="s3" kind="call"
fn="std.storage.doc.query"
arg name="collection" lit="users"
arg name="filter" lit='{"status": "active"}'
arg name="order_by" lit="created_at"
arg name="order_dir" lit="desc"
arg name="limit" lit=10
as="results"
end
The filter parameter accepts a JSON object with these operators:
| Pattern | Example | Description |
|---|---|---|
| Exact match | {"status": "active"} |
Field equals value |
$gt, $gte, $lt, $lte |
{"age": {"$gt": 18}} |
Comparison |
$and |
{"$and": [{...}, {...}]} |
Logical AND |
$or |
{"$or": [{...}, {...}]} |
Logical OR |
$contains |
{"tags": {"$contains": "important"}} |
Array contains |
$starts_with |
{"name": {"$starts_with": "Jo"}} |
String prefix |
$ends_with |
{"email": {"$ends_with": "@co.com"}} |
String suffix |
$ne |
{"deleted_at": {"$ne": null}} |
Not equal |
null |
{"deleted_at": null} |
Is null |
For complex queries with compile-time type checking, use dialect="indexeddb" instead of the function API:
step id="s1" kind="query"
dialect="indexeddb"
target="std.storage"
select all
from="users"
where
and
equals field="status" lit="active"
greater field="age" lit=18
end
end
order by="created_at" dir="desc"
limit=10
as="active_users"
end