Skip to content
 
 

Latest commit

 

History

33 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sprites Elixir SDK

Elixir SDK for Sprites - a code container runtime for interactive development.

Installation

Add sprites to your list of dependencies in mix.exs. The package is not currently published on Hex, so use a Git dependency:

def deps do
  [
    {:sprites, git: "https://github.com/superfly/sprites-ex.git"}
  ]
end

Quick Start

# Create a client
client = Sprites.new(token, base_url: "https://api.sprites.dev")

# Get a sprite handle
sprite = Sprites.sprite(client, "my-sprite")

# Execute a command synchronously (like System.cmd/3)
{output, exit_code} = Sprites.cmd(sprite, "echo", ["hello"])
IO.puts(output)  # => "hello\n"

# Execute a command asynchronously (like Port message passing)
{:ok, command} = Sprites.spawn(sprite, "ls", ["-la"])

receive do
  {:stdout, ^command, data} -> IO.write(data)
  {:stderr, ^command, data} -> IO.write(:stderr, data)
  {:exit, ^command, code} -> IO.puts("Exited with: #{code}")
end

API Reference

Client Management

# Create a client
client = Sprites.new(token, base_url: "https://api.sprites.dev")

# Get a sprite handle (doesn't create the sprite)
sprite = Sprites.sprite(client, "my-sprite")

# Create a new sprite
{:ok, sprite} = Sprites.create(client, "new-sprite")

# Destroy a sprite
:ok = Sprites.destroy(sprite)

Command Execution

Synchronous (System.cmd-like)

# Basic execution
{output, exit_code} = Sprites.cmd(sprite, "echo", ["hello"])

# With options
{output, code} = Sprites.cmd(sprite, "ls", ["-la"],
  dir: "/app",
  env: [{"FOO", "bar"}],
  timeout: 30_000,
  stderr_to_stdout: true
)

# With TTY
{output, code} = Sprites.cmd(sprite, "bash", ["-c", "tty"],
  tty: true,
  tty_rows: 24,
  tty_cols: 80
)

Asynchronous (Port-like)

# Start a command
{:ok, command} = Sprites.spawn(sprite, "bash", ["-i"], tty: true)

# Messages are sent to the calling process:
# - {:stdout, command, data}
# - {:stderr, command, data}
# - {:exit, command, exit_code}
# - {:error, command, reason}

# Write to stdin
Sprites.write(command, "ls\n")

# Close stdin (send EOF)
Sprites.close_stdin(command)

# Wait for completion
{:ok, exit_code} = Sprites.await(command)

# Resize TTY
Sprites.resize(command, 40, 120)

Streaming

# Stream command output
sprite
|> Sprites.stream("tail", ["-f", "/var/log/app.log"])
|> Stream.filter(&String.contains?(&1, "ERROR"))
|> Stream.each(&Logger.error/1)
|> Stream.run()

REST/Session/Services APIs

# Paged sprite listing (non-breaking alternative to Sprites.list/2)
{:ok, page} = Sprites.list_page(client, max_results: 10)
page["sprites"]
page["next_continuation_token"]

# HTTP POST exec (non-websocket)
{:ok, result} = Sprites.exec_http(sprite, "python", ["-c", "print(1)"])

# List/attach/kill exec sessions
{:ok, sessions} = Sprites.list_sessions(sprite)
{:ok, cmd} = Sprites.attach_session(sprite, to_string(hd(sessions).id))
{:ok, kill_events} = Sprites.kill_session(sprite, to_string(hd(sessions).id), signal: "SIGTERM")

# Services lifecycle
{:ok, _service} =
  Sprites.upsert_service(sprite, "web", %{
    cmd: "python",
    args: ["-m", "http.server", "8000"],
    needs: [],
    http_port: 8000
  })

{:ok, _start_events} = Sprites.start_service(sprite, "web", duration: "5s")
{:ok, _log_events} = Sprites.service_logs(sprite, "web", lines: 100, duration: "0")
{:ok, _stop_events} = Sprites.stop_service(sprite, "web", timeout: "10s")

Test CLI

The SDK includes a test CLI for integration testing with the shared test harness:

cd test_cli
mix deps.get
mix escript.build

# Set auth token
export SPRITES_TOKEN=your-token

# Create a sprite
./test-cli create my-sprite

# Run a command
./test-cli -sprite my-sprite -output stdout echo hello

# Interactive TTY
./test-cli -sprite my-sprite -tty bash

# Destroy the sprite
./test-cli destroy my-sprite

CLI Flags

Flag Description
-base-url <url> API base URL (default: https://api.sprites.dev)
-sprite <name> Sprite name (required for exec)
-output <mode> Output mode: stdout, combined, exit-code, default
-tty Enable TTY mode
-tty-rows <n> TTY rows (default: 24)
-tty-cols <n> TTY columns (default: 80)
-timeout <dur> Command timeout (e.g., 10s, 5m)
-dir <path> Working directory
-env key=val Environment variables
-log-target <path> JSON event log file

Running SDK Tests

Run unit tests only (default):

mix test

Run live integration tests:

export SPRITES_TEST_TOKEN=your-token
# Optional:
export SPRITES_TEST_BASE_URL=https://api.sprites.dev

mix test.live
# equivalent:
# mix test --include integration --include live

By default, tests tagged with :integration and :live are excluded unless you include them explicitly.

Shared Harness

The Elixir SDK is compatible with the shared test harness:

cd /path/to/sprite-env/sdks/test
export SPRITES_TEST_TOKEN=your-token
export SDK_TEST_COMMAND=/path/to/sprites-ex/test_cli/test-cli
make test-all

License

MIT

About

An Elixir SDK for Sprites

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages