Skip to main content

dvm_api/
lib.rs

1//! dvm.run's REST API: what it takes and returns. dvm.run's controller
2//! serves it, and the SDKs and its panel call it; the controller, the panel
3//! and the Rust SDK check a sandbox's spec with the same code.
4//!
5//! A type that holds an invariant (a checked spec, an image reference) keeps
6//! its fields private; a plain record of what the controller answers has
7//! them public.
8
9mod api_key;
10mod capacity;
11mod cli_login;
12mod command;
13mod execution;
14mod file;
15mod image_reference;
16mod replay;
17mod run;
18mod sandbox;
19mod timestamp;
20mod user;
21mod watched;
22
23pub use api_key::{ApiKey, CreatedApiKey, NewApiKey};
24pub use capacity::Capacity;
25pub use cli_login::{CliLogin, CollectCliLogin, NewCliLogin, StartedCliLogin};
26pub use command::{
27    CommandLine, CommandNumber, CommandOutputEvent, CommandSignal, CommandState, CommandStdin,
28    NewCommand, SandboxCommand,
29};
30pub use execution::Execution;
31pub use file::{FileMode, SandboxPath};
32pub use image_reference::{ImageReference, InvalidImageReference};
33pub use replay::{
34    MachineState, MemoryRegion, Moment, NewReplay, OpenFile, ProcessState, ReplayStop, Seek,
35    StoppedThread, ThreadState, ThreadWait,
36};
37pub use run::{
38    ByteChunk, InvalidRunAction, OutputStream, ReplayVerdict, Run, RunAction, RunId, RunOutput,
39    RunState,
40};
41pub use sandbox::{
42    EnvironmentVariable, Sandbox, SandboxDraft, SandboxId, SandboxSpec, SandboxesPage, SpecError,
43    SpecField,
44};
45pub use timestamp::Timestamp;
46pub use user::{Me, UserLimits};
47pub use watched::{EventPosition, WatchKind, WatchKinds, WatchedEvent, WatchedEvents};
48
49use serde::{Deserialize, Serialize};
50
51/// What the controller answers instead, when it refuses a request: the body
52/// of every response that isn't a success.
53#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
54#[cfg_attr(feature = "typescript", derive(ts_rs::TS))]
55#[cfg_attr(feature = "typescript", ts(export_to = "controller-api.ts"))]
56pub struct ApiError {
57    pub message: String,
58}
59
60/// Writes every type's TypeScript, with the types it names, into
61/// `controller-api.ts` in `config`'s directory: the panel's API.
62#[cfg(feature = "typescript")]
63pub fn export_typescript(config: &ts_rs::Config) -> Result<(), ts_rs::ExportError> {
64    use ts_rs::TS;
65    ApiError::export_all(config)?;
66    ApiKey::export_all(config)?;
67    ByteChunk::export_all(config)?;
68    Capacity::export_all(config)?;
69    CliLogin::export_all(config)?;
70    CommandLine::export_all(config)?;
71    CommandNumber::export_all(config)?;
72    CommandOutputEvent::export_all(config)?;
73    CommandSignal::export_all(config)?;
74    CommandState::export_all(config)?;
75    CommandStdin::export_all(config)?;
76    CreatedApiKey::export_all(config)?;
77    EnvironmentVariable::export_all(config)?;
78    EventPosition::export_all(config)?;
79    Execution::export_all(config)?;
80    FileMode::export_all(config)?;
81    ImageReference::export_all(config)?;
82    MachineState::export_all(config)?;
83    Me::export_all(config)?;
84    MemoryRegion::export_all(config)?;
85    Moment::export_all(config)?;
86    NewApiKey::export_all(config)?;
87    NewCommand::export_all(config)?;
88    NewReplay::export_all(config)?;
89    OpenFile::export_all(config)?;
90    OutputStream::export_all(config)?;
91    ProcessState::export_all(config)?;
92    ReplayStop::export_all(config)?;
93    ReplayVerdict::export_all(config)?;
94    Run::export_all(config)?;
95    RunAction::export_all(config)?;
96    RunId::export_all(config)?;
97    RunOutput::export_all(config)?;
98    RunState::export_all(config)?;
99    Sandbox::export_all(config)?;
100    SandboxCommand::export_all(config)?;
101    SandboxDraft::export_all(config)?;
102    SandboxId::export_all(config)?;
103    SandboxPath::export_all(config)?;
104    SandboxSpec::export_all(config)?;
105    SandboxesPage::export_all(config)?;
106    Seek::export_all(config)?;
107    StoppedThread::export_all(config)?;
108    ThreadState::export_all(config)?;
109    ThreadWait::export_all(config)?;
110    Timestamp::export_all(config)?;
111    UserLimits::export_all(config)?;
112    WatchKind::export_all(config)?;
113    WatchKinds::export_all(config)?;
114    WatchedEvent::export_all(config)?;
115    WatchedEvents::export_all(config)?;
116    Ok(())
117}
118
119#[cfg(all(test, feature = "typescript"))]
120mod typescript_tests {
121    #[test]
122    fn every_type_is_written_to_one_file() {
123        let directory = std::env::temp_dir().join(format!("dvm-api-{}", std::process::id()));
124        let config = ts_rs::Config::from_env().with_out_dir(&directory);
125        super::export_typescript(&config).unwrap();
126        let written = std::fs::read_to_string(directory.join("controller-api.ts")).unwrap();
127        std::fs::remove_dir_all(&directory).unwrap();
128        for declaration in [
129            "export type Sandbox = ",
130            "export type ApiError = ",
131            "export type Me = ",
132        ] {
133            assert!(written.contains(declaration), "{declaration}");
134        }
135    }
136}