Skip to main content
The operations system automatically generates type-safe Swift and TypeScript clients from Rust API definitions. Define your API once in Rust and get native clients for iOS, web, and desktop without manual synchronization.

How It Works

The system uses compile-time type extraction to discover all operations and generate client code during the build process. This eliminates the traditional API boundary.

Define Operations

Operations are either Actions (write) or Queries (read):

Register and Generate

Register the operation with a single macro:
The build process automatically:
  1. Extracts type information using Specta
  2. Generates Swift and TypeScript type definitions
  3. Creates native API methods for each client

Use Generated Clients

Swift:
TypeScript:

Operation Types

Actions

Actions modify state and typically return job receipts or updated entities:

Validation and Confirmation

Actions support a validation phase that can request user confirmation before execution. This enables safe, interactive operations with clear user feedback.

ValidationResult

The validate() method returns one of two results:

Example: File Copy with Conflict Resolution

CLI Integration

The CLI handles confirmations interactively:
The validate() method takes &self (a reference), while execute() takes self (consumes the action). This ensures validation doesn’t modify state, while execution can take ownership to transform the action into its result.

Queries

Queries retrieve data without side effects:

Type System

All standard Rust types are supported through Specta:
The Type derive is required for all types used in operations. This enables Specta to extract type information for client generation.

Wire Protocol

Operations use a consistent wire protocol:
  • Actions: action:{category}.{operation}.input.v{version}
  • Queries: query:{scope}.{operation}.v{version}
Examples:
  • action:files.copy.input
  • query:library.stats

Adding Operations

1. Create Input/Output Types

2. Implement the Operation

For a query:

3. Register It

4. Build and Use

After building, the operation is available in all clients automatically.

iOS Integration

The iOS app embeds the Rust core and communicates through FFI:
Swift calls through the FFI boundary using the generated types.

Code Generation Details

Build Process

The build script runs during cargo build:

Type Extraction

A binary extracts all registered operations:

Registration Internals

The registration macros use inventory for compile-time collection:

Best Practices

Operation Design

Keep operations focused with clear inputs and outputs. Use appropriate scopes (Library vs Core) based on whether the operation needs library context.

When to Use Validation Confirmations

Use the confirmation pattern for operations that:
  1. Have Destructive Side Effects: Deleting files, overwriting data, or making irreversible changes
  2. Encounter Conflicts: File name collisions, duplicate entries, or conflicting states
  3. Need User Decisions: Multiple valid approaches where user preference matters
  4. Risk Data Loss: Operations that could result in unexpected data loss
Examples of good confirmation use cases:
  • File copy/move when destination exists
  • Deleting non-empty directories
  • Overwriting modified files
  • Removing locations with indexed content
  • Irreversible format conversions
Keep confirmations minimal - only ask when truly necessary. Don’t confirm routine operations or when the intent is already clear from the input.

Type Design

Flatten structures when possible and use Rust enums for variants. Document fields as comments flow through to generated code.

Error Handling

Define specific error types for each operation:

Performance

For large result sets, consider pagination or streaming:

Advanced Features

Batch Operations

Operation Metadata

Actions can define metadata for UI presentation:
Confirmation is handled dynamically through the validate() method, not as static metadata. This allows context-aware confirmations based on the actual operation state.
Run cargo run --bin generate_swift_types to debug type extraction issues. Check the generated files in packages/swift/Sources/SpacedriveClient/Generated/.
The operations system eliminates manual API maintenance while providing type-safe, performant clients across all platforms.