diff --git a/crates/omnigraph-cli/src/main.rs b/crates/omnigraph-cli/src/main.rs index 7951f37..8c68759 100644 --- a/crates/omnigraph-cli/src/main.rs +++ b/crates/omnigraph-cli/src/main.rs @@ -18,7 +18,7 @@ use omnigraph_server::api::{ BranchCreateOutput, BranchCreateRequest, BranchDeleteOutput, BranchListOutput, BranchMergeOutput, BranchMergeRequest, ChangeOutput, ChangeRequest, CommitListOutput, CommitOutput, ErrorOutput, ExportRequest, IngestOutput, IngestRequest, ReadOutput, ReadRequest, - RunListOutput, RunOutput, SchemaApplyOutput, SchemaApplyRequest, SnapshotOutput, + RunListOutput, RunOutput, SchemaApplyOutput, SchemaApplyRequest, SchemaGetOutput, SnapshotOutput, SnapshotTableOutput, commit_output, ingest_output, read_output, run_output, schema_apply_output, snapshot_payload, }; @@ -303,6 +303,17 @@ enum SchemaCommand { #[arg(long)] json: bool, }, + /// Get the current accepted schema source + Get { + /// Repo URI + uri: Option, + #[arg(long)] + target: Option, + #[arg(long)] + config: Option, + #[arg(long)] + json: bool, + }, } #[derive(Debug, Subcommand)] @@ -2003,6 +2014,37 @@ async fn main() -> Result<()> { print_schema_apply_human(&output); } } + SchemaCommand::Get { + uri, + target, + config, + json, + } => { + let config = load_cli_config(config.as_ref())?; + let bearer_token = + resolve_remote_bearer_token(&config, uri.as_deref(), target.as_deref())?; + let uri = resolve_uri(&config, uri, target.as_deref())?; + let output = if is_remote_uri(&uri) { + remote_json::( + &http_client, + Method::GET, + remote_url(&uri, "/schema"), + None, + bearer_token.as_deref(), + ) + .await? + } else { + let db = Omnigraph::open(&uri).await?; + SchemaGetOutput { + source: db.schema_source().to_string(), + } + }; + if json { + print_json(&output)?; + } else { + print!("{}", output.source); + } + } }, Command::Query { command } => match command { QueryCommand::Lint { diff --git a/crates/omnigraph-server/src/api.rs b/crates/omnigraph-server/src/api.rs index ff5d453..ac5cd82 100644 --- a/crates/omnigraph-server/src/api.rs +++ b/crates/omnigraph-server/src/api.rs @@ -280,6 +280,11 @@ pub struct SchemaApplyOutput { pub steps: Vec, } +#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] +pub struct SchemaGetOutput { + pub source: String, +} + #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] pub struct IngestRequest { pub branch: Option, diff --git a/crates/omnigraph-server/src/lib.rs b/crates/omnigraph-server/src/lib.rs index e8d0e7d..adef1c4 100644 --- a/crates/omnigraph-server/src/lib.rs +++ b/crates/omnigraph-server/src/lib.rs @@ -14,7 +14,7 @@ use api::{ BranchMergeOutput, BranchMergeRequest, ChangeOutput, ChangeRequest, CommitListOutput, CommitListQuery, ErrorCode, ErrorOutput, ExportRequest, HealthOutput, IngestOutput, IngestRequest, ReadOutput, ReadRequest, RunListOutput, SchemaApplyOutput, SchemaApplyRequest, - SnapshotQuery, ingest_output, schema_apply_output, snapshot_payload, + SchemaGetOutput, SnapshotQuery, ingest_output, schema_apply_output, snapshot_payload, }; use axum::body::{Body, Bytes}; use axum::extract::DefaultBodyLimit; @@ -63,6 +63,7 @@ use utoipa::openapi::security::{Http, HttpAuthScheme, SecurityScheme}; server_export, server_change, server_schema_apply, + server_schema_get, server_ingest, server_branch_list, server_branch_create, @@ -407,6 +408,7 @@ pub fn build_app(state: AppState) -> Router { .route("/export", post(server_export)) .route("/read", post(server_read)) .route("/change", post(server_change)) + .route("/schema", get(server_schema_get)) .route("/schema/apply", post(server_schema_apply)) .route( "/ingest", @@ -796,6 +798,41 @@ async fn server_change( })) } +#[utoipa::path( + get, + path = "/schema", + tag = "schema", + responses( + (status = 200, description = "Current schema source", body = SchemaGetOutput), + (status = 401, description = "Unauthorized", body = ErrorOutput), + (status = 403, description = "Forbidden", body = ErrorOutput), + ), + security(("bearer_token" = [])), +)] +async fn server_schema_get( + State(state): State, + actor: Option>, +) -> std::result::Result, ApiError> { + authorize_request( + &state, + actor.as_ref().map(|Extension(actor)| actor), + PolicyRequest { + actor_id: actor + .as_ref() + .map(|Extension(actor)| actor.as_str().to_string()) + .unwrap_or_default(), + action: PolicyAction::Read, + branch: None, + target_branch: None, + }, + )?; + let source = { + let db = Arc::clone(&state.db).read_owned().await; + db.schema_source().to_string() + }; + Ok(Json(SchemaGetOutput { source })) +} + #[utoipa::path( post, path = "/schema/apply", diff --git a/crates/omnigraph-server/tests/openapi.rs b/crates/omnigraph-server/tests/openapi.rs index f47ccdf..d8e0cc7 100644 --- a/crates/omnigraph-server/tests/openapi.rs +++ b/crates/omnigraph-server/tests/openapi.rs @@ -161,6 +161,7 @@ const EXPECTED_PATHS: &[&str] = &[ "/read", "/export", "/change", + "/schema", "/schema/apply", "/ingest", "/branches",