@reventlessdev/rescript-ssh2
v1.1.0-alpha.12
Published
ReScript bindings for ssh2
Readme
@reventlessdev/rescript-ssh2
⚠️ Alpha. APIs can change without notice between releases. Pin exact versions and expect breaking changes.
ReScript bindings for ssh2 - SSH2 client and server modules for Node.js.
Install
pnpm add @reventlessdev/rescript-ssh2Add it to your rescript.json dependencies:
{
"dependencies": ["@reventlessdev/rescript-ssh2"]
}API Overview
SSH2.Client
The Client module provides SSH connection functionality.
Creating a Client
let client = SSH2.Client.make()Connection Configuration
type config = {
host?: string, // Hostname or IP address (default: "localhost")
port?: int, // Port number (default: 22)
forceIPv4?: bool, // Force IPv4 only
forceIPv6?: bool, // Force IPv6 only
username?: string, // Username for authentication
password?: string, // Password for password-based authentication
privateKey?: string, // Private key for key-based authentication
passphrase?: string, // Passphrase for encrypted private key
readyTimeout?: int, // Timeout in ms (default: 20000)
debug?: string => unit, // Debug output function
}Client Methods
connect(client, config)- Initiate SSH connectionend_(client)- Close SSH connectiononReady(client, callback)- Handle connection ready eventonError(client, errorHandler)- Handle connection errorsonTimeout(client, callback)- Handle connection timeoutonEnd(client, callback)- Handle connection end event
SFTP Operations
SFTP functionality is provided at the module level after establishing an SFTP session.
Starting an SFTP Session
SSH2.make(client, (error, sftp) => {
switch error {
| Some(err) => Console.error("SFTP Error:", err)
| None => // Use sftp
}
})SFTP Methods
readdir(sftp, ~dirName, callback)- List directory contents- Returns array of entities with
filename,longname, andattrs(size, uid, gid, atime, mtime)
- Returns array of entities with
createReadStream(sftp, ~path, ~options?)- Create read stream for file- Options:
flags,encoding,handle,mode,autoClose,start,end
- Options:
createWriteStream(sftp, ~path, ~options?)- Create write stream for file- Options:
flags,encoding,mode
- Options:
fastGet(sftp, ~remotePath, ~localPath, ~options?, ~callback)- Fast file download- Options:
concurrency,chunkSize,step(progress callback)
- Options:
onError(sftp, errorHandler)- Handle SFTP errorsonEnd(sftp, callback)- Handle SFTP session endonClose(sftp, callback)- Handle SFTP session close
Examples
Basic SSH Connection with Password Authentication
let client = SSH2.Client.make()
client
->SSH2.Client.onReady(client => {
Console.log("SSH connection ready")
client->SSH2.Client.end_()
})
->SSH2.Client.onError(err => {
Console.error("Connection error:", err)
})
->SSH2.Client.onEnd(() => {
Console.log("Connection closed")
})
->SSH2.Client.connect({
host: "example.com",
port: 22,
username: "myuser",
password: "mypassword",
})SSH Connection with Private Key
open NodeJs
let privateKey = Fs.readFileSync("~/.ssh/id_rsa", #utf8)
let client = SSH2.Client.make()
client
->SSH2.Client.onReady(client => {
Console.log("Authenticated with private key")
client->SSH2.Client.end_()
})
->SSH2.Client.connect({
host: "example.com",
username: "myuser",
privateKey: privateKey,
})SFTP: List Directory Contents
let client = SSH2.Client.make()
client
->SSH2.Client.onReady(client => {
SSH2.make(client, (error, sftp) => {
switch error {
| Some(err) => Console.error("SFTP Error:", err)
| None =>
sftp->SSH2.readdir(~dirName="/path/to/directory", (error, list) => {
switch error {
| Some(err) => Console.error("Readdir error:", SSH2.toJsError(err))
| None =>
list->Array.forEach(entity => {
Console.log(`${entity.filename} (${entity.attrs.size->Int.toString} bytes)`)
})
}
sftp->SSH2.end_()
client->SSH2.Client.end_()
})
}
})
})
->SSH2.Client.connect({
host: "example.com",
username: "myuser",
password: "mypassword",
})SFTP: Download File with Progress
let client = SSH2.Client.make()
client
->SSH2.Client.onReady(client => {
SSH2.make(client, (error, sftp) => {
switch error {
| Some(err) => Console.error("SFTP Error:", err)
| None =>
sftp->SSH2.fastGet(
~remotePath="/remote/path/file.txt",
~localPath="/local/path/file.txt",
~options={
concurrency: 64,
chunkSize: 32768,
step: (~totalTransferred, ~chunk, ~total) => {
let percent = (totalTransferred->Int.toFloat /. total->Int.toFloat *. 100.0)
Console.log(`Downloaded: ${percent->Float.toString}%`)
},
},
~callback=error => {
switch error {
| Some(err) => Console.error("Download error:", err)
| None => Console.log("Download complete")
}
sftp->SSH2.end_()
client->SSH2.Client.end_()
},
)
}
})
})
->SSH2.Client.connect({
host: "example.com",
username: "myuser",
password: "mypassword",
})SFTP: Upload File Using Stream
open NodeJs
let client = SSH2.Client.make()
client
->SSH2.Client.onReady(client => {
SSH2.make(client, (error, sftp) => {
switch error {
| Some(err) => Console.error("SFTP Error:", err)
| None =>
let readStream = Fs.createReadStream("/local/path/file.txt")
let writeStream = sftp->SSH2.createWriteStream(
~path="/remote/path/file.txt",
~options={mode: 0o644},
)
readStream->NodeStreams.Readable.pipe(writeStream)
writeStream
->NodeStreams.Writable.onFinish(() => {
Console.log("Upload complete")
sftp->SSH2.end_()
client->SSH2.Client.end_()
})
->NodeStreams.Writable.onError(err => {
Console.error("Upload error:", err)
sftp->SSH2.end_()
client->SSH2.Client.end_()
})
}
})
})
->SSH2.Client.connect({
host: "example.com",
username: "myuser",
password: "mypassword",
})Error Handling
The bindings provide proper error handling through option types and callbacks:
// Client errors
client->SSH2.Client.onError(err => {
Console.error("SSH Error:", err)
})
// SFTP errors
sftp->SSH2.onError(err => {
Console.error("SFTP Error:", SSH2.toJsError(err))
})Type Conversions
SSH2.toSftpError(Js.Exn.t)- Convert JS error to SFTP errorSSH2.toJsError(error)- Convert SFTP error to JS error
References
Links
- 📚 Documentation — docs.reventless.dev
- 📦 Repository — ReventlessDev/reventless-core
- 📋 Changelog
