API Reference
Everything You Can Build With
All the modules, functions, and capabilities built into Hype. TUI components, HTTP servers, databases, crypto, plugins, and moreβeverything you need to ship complete applications.
π§© Core Modules
TUI Module
Terminal User Interface components for building interactive console applications
View APITUI Module
The TUI module provides terminal-based user interface components using the tview library.
Application Management
local app = tui.newApp()
App Methods
app:SetRoot(primitive, fullscreen)
- Set the root componentapp:Run()
- Start the application event loopapp:Stop()
- Stop the applicationapp:SetFocus(primitive)
- Set focus to a specific componentapp:Draw()
- Queue a redrawapp:SetInputCapture(function)
- Set global key handler
UI Components
TextView
Display text content with advanced formatting, styling, and scrolling capabilities.
local textView = tui.newTextView(text)
Content & Behavior:
textView:SetText(text)
- Set display texttextView:GetText()
- Get current texttextView:SetWrap(bool)
- Enable/disable text wrappingtextView:SetWordWrap(bool)
- Enable/disable word wrappingtextView:SetScrollable(bool)
- Make content scrollabletextView:SetRegions(bool)
- Enable clickable regions
Enhanced Styling:
textView:SetDynamicColors(bool)
- Enable color markup parsingtextView:SetBorder(bool)
- Add border around componenttextView:SetBorderColor(color)
- Set border colortextView:SetBackgroundColor(color)
- Set background colortextView:SetTitle(title)
- Set component titletextView:SetTextColor(color)
- Set text color
InputField
Text input component for user data entry with enhanced styling options.
local inputField = tui.newInputField()
Content & Behavior:
inputField:SetLabel(label)
- Set field labelinputField:SetPlaceholder(text)
- Set placeholder textinputField:GetText()
- Get current input textinputField:SetText(text)
- Set input textinputField:SetDoneFunc(callback)
- Set completion callback
Enhanced Styling:
inputField:SetBorder(bool)
- Add border around input fieldinputField:SetBorderColor(color)
- Set border colorinputField:SetFieldBackgroundColor(color)
- Set input backgroundinputField:SetFieldTextColor(color)
- Set input text colorinputField:SetTitle(title)
- Set component title
Button
Clickable button component for user actions with professional styling.
local button = tui.newButton(label)
Content & Behavior:
button:SetLabel(label)
- Set button labelbutton:SetSelectedFunc(callback)
- Set click handler
Enhanced Styling:
button:SetBorder(bool)
- Add border around buttonbutton:SetBorderColor(color)
- Set border colorbutton:SetBackgroundColor(color)
- Set button backgroundbutton:SetLabelColor(color)
- Set button text colorbutton:SetTitle(title)
- Set component title
Flex
Flexible layout container for organizing components with styling support.
local flex = tui.newFlex()
Layout & Behavior:
flex:SetDirection(direction)
- Set layout direction (0=vertical, 1=horizontal)flex:AddItem(primitive, fixedSize, proportion, focus)
- Add component to layout
Enhanced Styling:
flex:SetBorder(bool)
- Add border around containerflex:SetBorderColor(color)
- Set border colorflex:SetBackgroundColor(color)
- Set container backgroundflex:SetTitle(title)
- Set container title
Color Styling & Theming
Enhanced TUI components support professional color schemes and markup.
Color Constants (256-color palette)
-- Common color constants for consistent theming
local COLORS = {
PRIMARY = 39, -- Bright blue
SUCCESS = 46, -- Bright green
WARNING = 226, -- Bright yellow
DANGER = 196, -- Bright red
SECONDARY = 245, -- Light gray
DARK = 235, -- Dark gray
DARKER = 232, -- Very dark gray
LIGHT = 255, -- White
ACCENT = 201, -- Bright magenta
INFO = 51 -- Bright cyan
}
Dynamic Color Markup
Use color markup in text content when SetDynamicColors(true)
is enabled:
-- Color markup format: [color_code]text[reset_color]
textView:SetDynamicColors(true)
textView:SetText("[46]SUCCESS:[255] Operation completed!")
-- Advanced example with multiple colors
local statusText = string.format([[
[%d]π Welcome to Dashboard![%d]
[%d]Status:[%d] %s
[%d]Uptime:[%d] %s
]],
COLORS.PRIMARY, COLORS.LIGHT,
COLORS.INFO, COLORS.LIGHT, "Online",
COLORS.SUCCESS, COLORS.LIGHT, "2 days"
)
Professional Styling Example
-- Create a professionally styled component
local panel = tui.newTextView("")
panel:SetDynamicColors(true)
panel:SetBorder(true)
panel:SetTitle("π System Metrics")
panel:SetBorderColor(COLORS.INFO)
panel:SetBackgroundColor(COLORS.DARK)
panel:SetScrollable(true)
-- Button with custom styling
local button = tui.newButton("π Execute")
button:SetBorder(true)
button:SetBorderColor(COLORS.SUCCESS)
button:SetBackgroundColor(COLORS.SUCCESS)
button:SetLabelColor(COLORS.LIGHT)
Event Handling
Event objects in input capture callbacks provide:
event:Key()
- Get key codeevent:Rune()
- Get character rune
Example: Enhanced TUI App
local app = tui.newApp()
local textView = tui.newTextView("[39]Hello from Hype![255]")
textView:SetDynamicColors(true)
textView:SetBorder(true)
textView:SetTitle("π My Enhanced App")
textView:SetBorderColor(39) -- Blue border
textView:SetBackgroundColor(235) -- Dark background
app:SetInputCapture(function(event)
if event:Key() == 27 then -- ESC key
app:Stop()
return nil
end
return event
end)
app:SetRoot(textView, true)
app:Run()
HTTP Module
Provides HTTP client and server functionality for web services and API development.
HTTP Client
local http = require('http')
GET Requests
local response, err = http.get(url, options)
Parameters:
url
- Target URL stringoptions
- Optional table with:timeout
- Request timeout in secondsheaders
- Custom headers table
Response Structure:
{
status = 200,
body = "response body",
headers = { ["Content-Type"] = "application/json" }
}
Example: HTTP Client Usage
local http = require('http')
local response, err = http.get("https://api.example.com/data", {
timeout = 10,
headers = {["User-Agent"] = "MyApp/1.0"}
})
if response then
print("Status:", response.status)
print("Body:", response.body)
else
print("Error:", err)
end
HTTP Server
local server = http.newServer()
Server Methods
server:handle(pattern, handler)
- Register route handlerserver:listen(port)
- Start server on portserver:stop()
- Stop server
Handler Function
Handler functions receive request and response objects:
server:handle("/api/users", function(req, res)
-- Request object (req) contains:
-- req.method, req.url, req.path, req.headers, req.query, req.body
-- Response object (res) methods:
res:write(content) -- Write text response
res:json(table) -- Write JSON response
res:status(code) -- Set HTTP status code
res:header(key, value) -- Set response header
end)
Example: HTTP Server
local http = require('http')
local server = http.newServer()
server:handle("/", function(req, res)
res:json({ message = "Hello World!" })
end)
server:handle("/api/echo", function(req, res)
res:json({
method = req.method,
path = req.path,
query = req.query,
body = req.body
})
end)
server:listen(8080)
print("Server running on :8080")
WebSocket Module
Real-time bidirectional communication with WebSocket servers and clients for building interactive applications.
WebSocket Server
local websocket = require('websocket')
local server = websocket.newServer()
Server Methods
server:handle(path, handler)
- Register WebSocket route handlerserver:listen(port)
- Start server on portserver:stop()
- Stop server gracefully
Connection Handler
Route handlers receive a WebSocket connection object:
server:handle("/ws", function(conn)
-- Set up event handlers for this connection
conn:onMessage(function(message)
print("Received:", message.data)
conn:send("Echo: " .. message.data)
end)
conn:onClose(function()
print("Connection closed")
end)
conn:onError(function(err)
print("Error:", err)
end)
-- Send welcome message
conn:send("Connected to WebSocket server!")
end)
Example: WebSocket Echo Server
local websocket = require('websocket')
local server = websocket.newServer()
server:handle("/echo", function(conn)
print("New WebSocket connection")
conn:onMessage(function(message)
print("Received:", message.data)
-- Echo message back to client
conn:send("Echo: " .. message.data)
end)
conn:onClose(function()
print("Client disconnected")
end)
conn:onError(function(err)
print("WebSocket error:", err)
end)
-- Send welcome message
conn:send("Welcome to echo server!")
end)
server:listen(8080)
print("WebSocket server running at ws://localhost:8080/echo")
-- Keep server running
while true do
os.execute("sleep 1")
end
WebSocket Client
local client = websocket.connect(url)
Parameters:
url
- WebSocket URL (e.g., "ws://localhost:8080/ws")
Returns: WebSocket connection object or nil on failure
Example: WebSocket Client
local websocket = require('websocket')
local client = websocket.connect("ws://localhost:8080/echo")
if not client then
print("Failed to connect to WebSocket server")
os.exit(1)
end
-- Set up event handlers
client:onMessage(function(message)
print("Received:", message.data)
print("Type:", message.type) -- "text" or "binary"
end)
client:onClose(function()
print("Connection closed")
end)
client:onError(function(err)
print("WebSocket error:", err)
end)
-- Send messages
client:send("Hello from Lua client!")
client:sendBinary("Binary message")
-- Ping the server
client:ping()
-- Close when done
client:close()
Connection Methods
Both server and client connections support these methods:
conn:send(message)
- Send text messageconn:sendBinary(data)
- Send binary messageconn:onMessage(handler)
- Set message event handlerconn:onClose(handler)
- Set close event handlerconn:onError(handler)
- Set error event handlerconn:close()
- Close connectionconn:ping()
- Send ping frame
Message Object Structure
{
data = "message content", -- String content of the message
type = "text" -- "text" or "binary"
}
Real-Time Chat Example
Multi-Client Chat Server
local websocket = require('websocket')
local clients = {}
local server = websocket.newServer()
server:handle("/chat", function(conn)
-- Add client to list
table.insert(clients, conn)
local clientId = #clients
print("Client " .. clientId .. " connected")
-- Broadcast join message
for i, client in ipairs(clients) do
if client ~= conn then
client:send("Client " .. clientId .. " joined")
end
end
conn:onMessage(function(message)
local msg = "Client " .. clientId .. ": " .. message.data
print(msg)
-- Broadcast to all clients
for i, client in ipairs(clients) do
client:send(msg)
end
end)
conn:onClose(function()
-- Remove client from list
for i, client in ipairs(clients) do
if client == conn then
table.remove(clients, i)
break
end
end
-- Notify others
for i, client in ipairs(clients) do
client:send("Client " .. clientId .. " left")
end
end)
end)
server:listen(8080)
print("Chat server running at ws://localhost:8080/chat")
Key-Value Module
BoltDB-based embedded database for persistent storage with ACID transactions.
Database Connection
local kv = require('kv')
local db, err = kv.open(path, options)
Parameters:
path
- Database file pathoptions
- Optional configuration table
Bucket Management
db:open_db(bucketName)
- Create/open bucket
Buckets are like tables in traditional databases, used to organize key-value pairs.
Basic Operations
db:put(bucket, key, value)
- Store key-value pairdb:get(bucket, key)
- Retrieve value by keydb:delete(bucket, key)
- Delete keydb:close()
- Close database connection
Example: Basic Usage
local kv = require('kv')
local db, err = kv.open("./data.db")
if not db then
print("Error opening database:", err)
return
end
-- Create/open bucket
db:open_db("users")
-- Store data
db:put("users", "john", "John Doe")
db:put("users", "jane", "Jane Smith")
-- Retrieve data
local name = db:get("users", "john")
print("User:", name) -- Output: User: John Doe
-- Delete data
db:delete("users", "john")
-- Close database
db:close()
Batch Operations
db:keys(bucket, prefix)
- Get all keys (optionally with prefix)db:foreach(bucket, callback)
- Iterate over all key-value pairs
Example: Batch Operations
-- Get all keys
local keys = db:keys("users")
for i, key in ipairs(keys) do
print("Key:", key)
end
-- Get keys with prefix
local userKeys = db:keys("users", "user_")
-- Iterate over all key-value pairs
db:foreach("users", function(key, value)
print(key .. " = " .. value)
return true -- Continue iteration
end)
Transaction Support
Transactions provide ACID guarantees for multiple operations.
local txn, err = db:begin_txn(readonly)
Transaction Methods
txn:put(bucket, key, value)
- Store in transactiontxn:get(bucket, key)
- Retrieve in transactiontxn:delete(bucket, key)
- Delete in transactiontxn:commit()
- Commit transactiontxn:abort()
- Abort transaction
Example: Transactions
-- Begin read-write transaction
local txn, err = db:begin_txn(false)
if not txn then
print("Error starting transaction:", err)
return
end
-- Perform multiple operations
txn:put("users", "alice", "Alice Johnson")
txn:put("users", "bob", "Bob Wilson")
-- Get data within transaction
local alice = txn:get("users", "alice")
print("Alice:", alice)
-- Commit all changes
local success, err = txn:commit()
if not success then
print("Transaction failed:", err)
txn:abort()
end
Crypto Module
Professional-grade cryptography using JSON Web Key (JWK) format with support for RSA (including PSS), ECDSA, and Ed25519 algorithms, plus SHA-256/384/512 hashing with deep hashing support for complex data structures.
Getting Started
local crypto = require('crypto')
The crypto module provides modern cryptographic operations using the industry-standard JWK format for key management.
Key Generation
local jwk = crypto.generate_jwk(algorithm)
local jwk = crypto.generate_jwk(algorithm, key_size) -- RSA only
Supported Algorithms:
"RS256", "RS384", "RS512"
- RSA PKCS#1 v1.5 with SHA-256/384/512"PS256", "PS384", "PS512"
- RSA-PSS with SHA-256/384/512"ES256", "ES384", "ES512"
- ECDSA with SHA-256/384/512"EdDSA"
- Ed25519 (EdDSA)
Returns: JWK table with algorithm-specific fields
Example: Generate Different Key Types
-- Generate RSA key (default 2048-bit)
local rsa_key = crypto.generate_jwk("RS256")
print("RSA Key Type:", rsa_key.kty) -- "RSA"
-- Generate 4096-bit RSA key
local rsa_4096 = crypto.generate_jwk("RS256", 4096)
print("Generated 4096-bit RSA key")
-- Generate 3072-bit RSA-PSS key
local rsa_pss = crypto.generate_jwk("PS256", 3072)
print("Generated 3072-bit RSA-PSS key")
-- Generate ECDSA key
local ecdsa_key = crypto.generate_jwk("ES256")
print("ECDSA Key Type:", ecdsa_key.kty) -- "EC"
-- Generate Ed25519 key
local ed25519_key = crypto.generate_jwk("EdDSA")
print("Ed25519 Key Type:", ed25519_key.kty) -- "OKP"
RSA Key Sizes:
2048
- Default for RS256/PS2563072
- Default for RS384/RS512/PS384/PS5124096
- Maximum supported size for enhanced security
Digital Signatures
Signing
local signature = crypto.sign(jwk, message)
Parameters:
jwk
- Private JWK key (from generate_jwk)message
- String data to sign
Returns: Binary signature string or nil on error
Verification
local is_valid = crypto.verify(public_jwk, message, signature)
Parameters:
public_jwk
- Public JWK key (from jwk_to_public)message
- Original string datasignature
- Binary signature to verify
Returns: Boolean validation result
Example: Sign and Verify
local crypto = require('crypto')
-- Generate key pair
local private_key = crypto.generate_jwk("ES256")
local public_key = crypto.jwk_to_public(private_key)
-- Sign message
local message = "Important document content"
local signature = crypto.sign(private_key, message)
if signature then
print("β
Message signed successfully")
-- Verify signature
local is_valid = crypto.verify(public_key, message, signature)
if is_valid then
print("β
Signature verified!")
else
print("β Invalid signature")
end
else
print("β Signing failed")
end
Key Management
Extract Public Key
local public_jwk = crypto.jwk_to_public(private_jwk)
Extracts the public key component from a private JWK for sharing and verification.
Key Thumbprint
local thumbprint = crypto.jwk_thumbprint(jwk)
Generates a unique SHA-256 thumbprint for key identification (RFC 7638).
JSON Serialization
-- Export to JSON
local json_string = crypto.jwk_to_json(jwk)
-- Import from JSON
local jwk = crypto.jwk_from_json(json_string)
Convert JWK objects to/from JSON for storage and transmission.
Example: Key Management
local crypto = require('crypto')
-- Generate and manage keys
local private_key = crypto.generate_jwk("RS256")
local public_key = crypto.jwk_to_public(private_key)
-- Get unique identifier
local key_id = crypto.jwk_thumbprint(private_key)
print("Key ID:", key_id)
-- Serialize for storage
local private_json = crypto.jwk_to_json(private_key)
local public_json = crypto.jwk_to_json(public_key)
-- Save public key for sharing
local file = io.open("public_key.json", "w")
file:write(public_json)
file:close()
-- Later: load and use
local loaded_json = io.open("public_key.json"):read("*all")
local loaded_key = crypto.jwk_from_json(loaded_json)
print("Loaded key algorithm:", loaded_key.alg)
Hashing Functions
Basic Hash Functions
local hash = crypto.sha256(data)
local hash = crypto.sha384(data)
local hash = crypto.sha512(data)
Compute SHA-256, SHA-384, or SHA-512 hash of input data.
Parameters:
data
- String data to hash
Returns: Hexadecimal hash string
Generic Hash Function
local hash = crypto.hash(algorithm, data)
Parameters:
algorithm
- Hash algorithm: "sha256", "sha384", or "sha512"data
- String data to hash
Returns: Hexadecimal hash string or nil + error
Deep Hash Function
local hash = crypto.deep_hash(value, algorithm)
Compute a deterministic hash of complex data structures including nested tables.
Parameters:
value
- Any Lua value (string, number, boolean, nil, table)algorithm
- Optional: "sha256", "sha384", or "sha512" (defaults to "sha384")
Returns: Hexadecimal hash string or nil + error
Example: Hashing Operations
local crypto = require('crypto')
-- Basic hashing
local data = "Important data to hash"
local sha256 = crypto.sha256(data)
local sha384 = crypto.sha384(data)
local sha512 = crypto.sha512(data)
print("SHA-256:", sha256)
print("SHA-384:", sha384)
print("SHA-512:", sha512)
-- Generic hash function
local hash = crypto.hash("sha384", data)
print("Generic SHA-384:", hash)
-- Deep hashing for complex structures
local complex_data = {
user = {
id = 123,
name = "Alice",
roles = {"admin", "user"}
},
settings = {
theme = "dark",
notifications = true
},
timestamp = os.time()
}
-- Deep hash with SHA-384 (default)
local deep_hash = crypto.deep_hash(complex_data)
print("Deep hash:", deep_hash)
-- Deep hash with specific algorithm
local deep_sha256 = crypto.deep_hash(complex_data, "sha256")
print("Deep SHA-256:", deep_sha256)
-- Consistent hashing regardless of key order
local reordered = {
timestamp = os.time(),
settings = {
notifications = true,
theme = "dark"
},
user = {
roles = {"admin", "user"},
name = "Alice",
id = 123
}
}
local hash1 = crypto.deep_hash(complex_data)
local hash2 = crypto.deep_hash(reordered)
print("Hashes match:", hash1 == hash2) -- true
Use Cases for Hashing
- Data Integrity: Verify data hasn't been modified
- Cache Keys: Generate consistent keys for complex data
- Deduplication: Identify duplicate data structures
- API ETags: Generate entity tags for HTTP caching
- Audit Logs: Create tamper-evident records
Security Best Practices
- Key Storage: Store private keys securely, never in plain text
- Algorithm Choice: Use ES256 for most applications (fast + secure)
- Key Rotation: Regularly rotate keys and use thumbprints for identification
- Public Key Sharing: Only share public keys, never private keys
- Message Integrity: Always verify signatures before trusting data
Algorithm Comparison
Performance Characteristics:
βββββββββββ¬ββββββββββββββ¬ββββββββββββββ¬βββββββββββββββ¬ββββββββββββ
β Algorithmβ Key Size β Signature β Performance β Security β
βββββββββββΌββββββββββββββΌββββββββββββββΌβββββββββββββββΌββββββββββββ€
β RS256 β 2048 bits β 256 bytes β Slower β Good β
β PS256 β 2048 bits β 256 bytes β Slower β Better β
β ES256 β 256 bits β 64 bytes β Fast β Good β
β EdDSA β 256 bits β 64 bytes β Fastest β Good β
βββββββββββ΄ββββββββββββββ΄ββββββββββββββ΄βββββββββββββββ΄ββββββββββββ
Recommendations:
- ES256: Best general-purpose choice (NIST P-256)
- EdDSA: Fastest performance, modern alternative
- PS256/384/512: Use for RSA with enhanced security (PSS padding)
- RS256: Use when legacy RSA compatibility is required
HTTP Signatures Module
RFC-compliant HTTP message signing and verification for secure API communication, webhooks, and microservice authentication.
Getting Started
local crypto = require('crypto')
local httpsig = require('httpsig')
HTTP Signatures provide message-level security by cryptographically signing HTTP requests and responses using the draft-cavage-http-signatures specification.
HTTP Request Signing
local signed_result = httpsig.sign(message, options)
Message Structure (Request):
{
type = "request",
method = "POST", -- HTTP method
path = "/api/users", -- URL path
headers = { -- HTTP headers
["Host"] = "api.example.com",
["Content-Type"] = "application/json"
},
body = '{"name": "Alice"}' -- Message body
}
Signing Options:
{
jwk = private_key, -- Private JWK for signing
key_id = "my-key-2024", -- Key identifier
headers = {"(request-target)", "host", "date", "digest"}, -- Headers to sign
created = os.time(), -- Optional: signature creation time
expires = os.time() + 300 -- Optional: signature expiration
}
Returns: Table with signed headers or nil on error
Example: Sign HTTP Request
local crypto = require('crypto')
local httpsig = require('httpsig')
-- Generate signing key
local signing_key = crypto.generate_jwk("ES256")
-- Create request to sign
local request = {
type = "request",
method = "POST",
path = "/api/transfer",
headers = {
["Host"] = "bank-api.com",
["Content-Type"] = "application/json"
},
body = '{"amount": 1000, "to": "account123"}'
}
-- Sign the request
local signed = httpsig.sign(request, {
jwk = signing_key,
key_id = "client-2024",
headers = {"(request-target)", "host", "content-type", "digest", "date"}
})
if signed then
print("β
Request signed successfully")
print("Signature:", signed.headers.signature:sub(1, 50) .. "...")
print("Digest:", signed.headers.digest)
print("Date:", signed.headers.date)
else
print("β Signing failed")
end
HTTP Response Signing
Message Structure (Response):
{
type = "response",
status = 200, -- HTTP status code
headers = { -- HTTP headers
["Content-Type"] = "application/json",
["Server"] = "MyAPI/1.0"
},
body = '{"status": "success"}' -- Response body
}
Example: Sign HTTP Response
-- Server response signing
local server_key = crypto.generate_jwk("RS256")
local response = {
type = "response",
status = 201,
headers = {
["Content-Type"] = "application/json",
["Location"] = "/api/users/123"
},
body = '{"id": 123, "created": true}'
}
local signed_response = httpsig.sign(response, {
jwk = server_key,
key_id = "server-rsa-key",
headers = {"(status)", "content-type", "location", "digest", "date"}
})
if signed_response then
print("β
Response signed by server")
print("Status signed:", response.status)
end
Signature Verification
local result = httpsig.verify(message, options)
Verification Options:
{
jwk = public_key, -- Public JWK for verification
required_headers = {"host", "date"}, -- Headers that must be signed
max_age = 300 -- Max signature age in seconds
}
Returns: Verification result table
{
valid = true, -- Boolean: signature valid
key_id = "client-2024", -- Key ID from signature
algorithm = "ecdsa-256", -- Algorithm used
reason = "digest mismatch" -- Error reason if invalid
}
Example: Verify Signature
-- Extract public key for verification
local public_key = crypto.jwk_to_public(signing_key)
-- Verify received message
local verification = httpsig.verify(received_message, {
jwk = public_key,
required_headers = {"host", "content-type"},
max_age = 300 -- 5 minutes
})
if verification.valid then
print("β
Signature verified!")
print("Signed by:", verification.key_id)
print("Algorithm:", verification.algorithm)
-- Process trusted message
process_secure_request(received_message)
else
print("β Invalid signature:", verification.reason)
-- Reject untrusted message
return_error("Signature verification failed")
end
Digest Operations
Message digests ensure content integrity and are automatically included when body content is present.
Create Digest
local digest = httpsig.create_digest(content, algorithm)
Parameters:
content
- String content to hashalgorithm
- "sha256" or "sha512" (default: "sha256")
Verify Digest
local is_valid = httpsig.verify_digest(content, digest_header)
Example: Manual Digest Operations
local content = '{"sensitive": "data", "amount": 5000}'
-- Create digest
local digest = httpsig.create_digest(content, "sha256")
print("Digest:", digest) -- "SHA-256=base64encodedHash"
-- Verify digest
local is_valid = httpsig.verify_digest(content, digest)
print("Valid:", is_valid) -- true
-- Test with tampered content
local tampered = '{"sensitive": "HACKED", "amount": 5000}'
local tampered_valid = httpsig.verify_digest(tampered, digest)
print("Tampered valid:", tampered_valid) -- false
Security Features
- Automatic Digest Creation: Body content automatically hashed and signed
- Tampering Detection: Modified content fails verification
- Replay Protection: Timestamps prevent replay attacks
- Flexible Headers: Sign any combination of HTTP headers
- Multiple Algorithms: Support for RSA, ECDSA, and Ed25519
- Key Identification: Key IDs enable multi-key scenarios
Common Use Cases
Webhook Security
-- Sign webhook payload
local webhook_signature = httpsig.sign({
type = "request",
method = "POST",
path = "/webhook",
headers = {
["Host"] = "client.example.com",
["X-Event-Type"] = "user.created"
},
body = '{"user_id": 123, "event": "created"}'
}, {
jwk = webhook_signing_key,
key_id = "webhook-2024"
})
API Authentication
-- Client signs API request
local api_request = httpsig.sign({
type = "request",
method = "GET",
path = "/api/user/profile",
headers = {
["Host"] = "api.service.com",
["Authorization"] = "Bearer " .. access_token
}
}, {
jwk = client_key,
key_id = "client-app-2024",
headers = {"(request-target)", "host", "authorization", "date"}
})
Microservice Communication
-- Service-to-service authentication
local service_request = httpsig.sign({
type = "request",
method = "POST",
path = "/internal/process",
headers = {
["Host"] = "worker-service",
["X-Service-ID"] = "gateway-v1"
},
body = process_data
}, {
jwk = service_key,
key_id = "gateway-service",
created = os.time(),
expires = os.time() + 60 -- 1 minute expiry
})
Best Practices
- Always Sign Critical Headers: Include host, date, and content-type
- Use Digest for Body Content: Include "digest" header when signing requests with bodies
- Set Reasonable Expiration: Use expires or max_age to prevent replay attacks
- Validate Required Headers: Specify required_headers in verification
- Key Management: Use unique key_id values and rotate keys regularly
- Algorithm Selection: Use ES256 for most applications (fast + secure)
Plugin System
Extend Hype applications with versioned Lua modules that embed seamlessly into your executables.
Using Plugins
Plugins are loaded using the --plugins
command line flag and accessed in Lua using require()
.
Plugin Specifications
fs
- Simple name (uses auto-discovery)fs@1.0.0
- Name with specific versionmyfs=./path/to/plugin
- Custom alias with pathmyfs=./path/to/plugin@2.0.0
- Alias with path and version
Example: Using Plugins
-- app.lua
local fs = require("fs")
local config = require("config")
-- Use filesystem plugin
local content, err = fs.readFile("data.txt")
if content then
print("File content:", content)
else
print("Error:", err)
end
-- Use configuration plugin
config.load("app.conf")
local port = config.get("server", "port", 8080)
# Run with plugins
./hype run app.lua --plugins fs@1.0.0,config@2.1.0
# Build with embedded plugins
./hype build app.lua --plugins fs@1.0.0,config@2.1.0 -o myapp
Plugin Discovery
Hype automatically searches for plugins in conventional directories:
./plugins/[name]/
- Local plugins directory./examples/plugins/[name]/
- Example plugins./[name]-plugin/
- Plugin suffix convention./examples/plugins/[name]-plugin/
- Example plugin suffix
Example: Plugin Directory Structure
project/
βββ app.lua
βββ plugins/
β βββ fs/
β β βββ hype-plugin.yaml
β β βββ plugin.lua
β βββ utils/
β βββ hype-plugin.yaml
β βββ plugin.lua
βββ examples/
βββ plugins/
βββ fs-plugin/
βββ hype-plugin.yaml
βββ plugin.lua
Plugin Manifest
Each plugin requires a hype-plugin.yaml
manifest file:
name: "fs"
version: "1.0.0"
type: "lua"
main: "plugin.lua"
description: "Basic filesystem operations"
Manifest Fields
name
- Plugin identifier (required)version
- Semantic version string (required)type
- Plugin type, currently only "lua" (required)main
- Entry point file (required)description
- Human-readable description (optional)
Plugin Development
Plugins are standard Lua modules that return a table of functions:
Example: Simple Plugin
-- plugin.lua
local fs = {}
function fs.readFile(path)
local file = io.open(path, "r")
if not file then
return nil, "File not found: " .. path
end
local content = file:read("*all")
file:close()
return content, nil
end
function fs.writeFile(path, content)
local file = io.open(path, "w")
if not file then
return nil, "Cannot write file: " .. path
end
file:write(content)
file:close()
return true, nil
end
function fs.exists(path)
local file = io.open(path, "r")
if file then
file:close()
return true
end
return false
end
return fs
Version Management
Plugins support exact version matching for compatibility:
fs@1.0.0
- Exact version match requiredfs
orfs@latest
- Any version accepted- Version validation prevents compatibility issues
Example: Version-Specific Usage
# Use specific version
./hype run app.lua --plugins fs@1.0.0
# Use latest version
./hype run app.lua --plugins fs
# Multiple plugins with versions
./hype run app.lua --plugins fs@1.0.0,json@2.1.0,utils
Available Plugins
Hype includes example plugins for common use cases:
Filesystem Plugin (fs@1.0.0)
fs.readFile(path)
- Read file contentsfs.writeFile(path, content)
- Write file contentsfs.exists(path)
- Check file existencefs.size(path)
- Get file sizefs.listDir(path)
- List directory contentsfs.mkdir(path)
- Create directory
Enhanced Filesystem Plugin (fs@2.0.0)
- All v1.0.0 features plus:
fs.copyFile(src, dst)
- Copy filefs.moveFile(src, dst)
- Move filefs.deleteFile(path)
- Delete filefs.version()
- Get plugin version
Example: Filesystem Operations
local fs = require("fs")
-- Read configuration
local config, err = fs.readFile("config.json")
if not config then
print("Error:", err)
return
end
-- Create backup
local success, err = fs.copyFile("data.txt", "backup.txt")
if success then
print("Backup created successfully")
end
-- List files
local files, err = fs.listDir("./logs")
if files then
for _, file in ipairs(files) do
print("Found:", file)
end
end
Plugin Best Practices
- Error Handling: Return
nil, error_message
on failure - Consistent API: Follow standard Lua conventions
- Version Compatibility: Use semantic versioning
- Documentation: Include clear function descriptions
- Testing: Test plugins with
hype run
before building
Command Line Interface
Build and execution options for Hype applications.
Build Command
hype build script.lua [options]
Options
-o, --output NAME
- Set executable name--target PLATFORM
- Target platform (current, linux, windows, darwin)--plugins LIST
- Comma-separated list of plugins to embed
Build Examples
# Build for current platform
hype build myapp.lua
# Specify output name
hype build myapp.lua -o myserver
# Build with plugins
hype build myapp.lua --plugins fs@1.0.0,json -o myapp
# Cross-compile for different platforms
hype build myapp.lua --target linux
hype build myapp.lua --target windows
hype build myapp.lua --target darwin
Run Command
Run Lua scripts directly for development and testing.
hype run script.lua [--plugins LIST] [-- args...]
Options
--plugins LIST
- Comma-separated list of plugins to load
Run Examples
# Run script directly
hype run server.lua
# Run with plugins
hype run myapp.lua --plugins fs@1.0.0,json
# Pass command line arguments
hype run myapp.lua -- --port 3000 --debug
# Plugins with arguments
hype run myapp.lua --plugins fs@1.0.0 -- --debug
Command Line Arguments
Access arguments in your Lua scripts via the global arg
table:
arg[0]
- Script/executable namearg[1], arg[2], ...
- Command line arguments
Example: Argument Handling
-- args.lua
print("Script name:", arg[0])
print("Number of arguments:", #arg)
for i = 1, #arg do
print("Arg " .. i .. ":", arg[i])
end
-- Usage: hype run args.lua -- hello world 123
-- Output:
-- Script name: args.lua
-- Number of arguments: 3
-- Arg 1: hello
-- Arg 2: world
-- Arg 3: 123
Standard Lua Libraries
All standard Lua libraries are available in Hype applications:
Global Environment
Access to _G
and global functions
Package System
Module loading with require()
and package
Coroutines
Cooperative multitasking with coroutine
Table Operations
Data structure manipulation with table
File I/O
File operations with io
library
System Access
Operating system interface with os
String Processing
Text manipulation with string
Mathematics
Mathematical functions with math