dvm-api 0.1.0

dvm.run's REST API: what it takes and returns, checked
Documentation
//! dvm.run's REST API: what it takes and returns. dvm.run's controller
//! serves it, and the SDKs and its panel call it; the controller, the panel
//! and the Rust SDK check a sandbox's spec with the same code.
//!
//! A type that holds an invariant (a checked spec, an image reference) keeps
//! its fields private; a plain record of what the controller answers has
//! them public.

mod api_key;
mod capacity;
mod cli_login;
mod command;
mod execution;
mod file;
mod image_reference;
mod replay;
mod run;
mod sandbox;
mod timestamp;
mod user;
mod watched;

pub use api_key::{ApiKey, CreatedApiKey, NewApiKey};
pub use capacity::Capacity;
pub use cli_login::{CliLogin, CollectCliLogin, NewCliLogin, StartedCliLogin};
pub use command::{
    CommandLine, CommandNumber, CommandOutputEvent, CommandSignal, CommandState, CommandStdin,
    NewCommand, SandboxCommand,
};
pub use execution::Execution;
pub use file::{FileMode, SandboxPath};
pub use image_reference::{ImageReference, InvalidImageReference};
pub use replay::{
    MachineState, MemoryRegion, Moment, NewReplay, OpenFile, ProcessState, ReplayStop, Seek,
    StoppedThread, ThreadState, ThreadWait,
};
pub use run::{
    ByteChunk, InvalidRunAction, OutputStream, ReplayVerdict, Run, RunAction, RunId, RunOutput,
    RunState,
};
pub use sandbox::{
    EnvironmentVariable, Sandbox, SandboxDraft, SandboxId, SandboxSpec, SandboxesPage, SpecError,
    SpecField,
};
pub use timestamp::Timestamp;
pub use user::{Me, UserLimits};
pub use watched::{EventPosition, WatchKind, WatchKinds, WatchedEvent, WatchedEvents};

use serde::{Deserialize, Serialize};

/// What the controller answers instead, when it refuses a request: the body
/// of every response that isn't a success.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
#[cfg_attr(feature = "typescript", ts(export_to = "controller-api.ts"))]
pub struct ApiError {
    pub message: String,
}

/// Writes every type's TypeScript, with the types it names, into
/// `controller-api.ts` in `config`'s directory: the panel's API.
#[cfg(feature = "typescript")]
pub fn export_typescript(config: &ts_rs::Config) -> Result<(), ts_rs::ExportError> {
    use ts_rs::TS;
    ApiError::export_all(config)?;
    ApiKey::export_all(config)?;
    ByteChunk::export_all(config)?;
    Capacity::export_all(config)?;
    CliLogin::export_all(config)?;
    CommandLine::export_all(config)?;
    CommandNumber::export_all(config)?;
    CommandOutputEvent::export_all(config)?;
    CommandSignal::export_all(config)?;
    CommandState::export_all(config)?;
    CommandStdin::export_all(config)?;
    CreatedApiKey::export_all(config)?;
    EnvironmentVariable::export_all(config)?;
    EventPosition::export_all(config)?;
    Execution::export_all(config)?;
    FileMode::export_all(config)?;
    ImageReference::export_all(config)?;
    MachineState::export_all(config)?;
    Me::export_all(config)?;
    MemoryRegion::export_all(config)?;
    Moment::export_all(config)?;
    NewApiKey::export_all(config)?;
    NewCommand::export_all(config)?;
    NewReplay::export_all(config)?;
    OpenFile::export_all(config)?;
    OutputStream::export_all(config)?;
    ProcessState::export_all(config)?;
    ReplayStop::export_all(config)?;
    ReplayVerdict::export_all(config)?;
    Run::export_all(config)?;
    RunAction::export_all(config)?;
    RunId::export_all(config)?;
    RunOutput::export_all(config)?;
    RunState::export_all(config)?;
    Sandbox::export_all(config)?;
    SandboxCommand::export_all(config)?;
    SandboxDraft::export_all(config)?;
    SandboxId::export_all(config)?;
    SandboxPath::export_all(config)?;
    SandboxSpec::export_all(config)?;
    SandboxesPage::export_all(config)?;
    Seek::export_all(config)?;
    StoppedThread::export_all(config)?;
    ThreadState::export_all(config)?;
    ThreadWait::export_all(config)?;
    Timestamp::export_all(config)?;
    UserLimits::export_all(config)?;
    WatchKind::export_all(config)?;
    WatchKinds::export_all(config)?;
    WatchedEvent::export_all(config)?;
    WatchedEvents::export_all(config)?;
    Ok(())
}

#[cfg(all(test, feature = "typescript"))]
mod typescript_tests {
    #[test]
    fn every_type_is_written_to_one_file() {
        let directory = std::env::temp_dir().join(format!("dvm-api-{}", std::process::id()));
        let config = ts_rs::Config::from_env().with_out_dir(&directory);
        super::export_typescript(&config).unwrap();
        let written = std::fs::read_to_string(directory.join("controller-api.ts")).unwrap();
        std::fs::remove_dir_all(&directory).unwrap();
        for declaration in [
            "export type Sandbox = ",
            "export type ApiError = ",
            "export type Me = ",
        ] {
            assert!(written.contains(declaration), "{declaration}");
        }
    }
}