Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
515 changes: 515 additions & 0 deletions crates/engine/src/cmd/connection_browse.rs

Large diffs are not rendered by default.

17 changes: 7 additions & 10 deletions crates/engine/src/cmd/connections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ use crate::connections::{Connection, DATABASE_KINDS, DESKTOP_ONLY, KINDS};
use crate::render::rustgis_tiles::{s3, stac};
use crate::{CmdResult, CommandSpec as C, Session};

#[path = "connection_browse.rs"]
mod browse;

pub fn commands() -> Vec<C> {
vec![
C::new("connection.list", "List Connections", "Home › Add › Data Sources", list).view().params(
Expand All @@ -29,6 +32,9 @@ pub fn commands() -> Vec<C> {
C::new("connection.test", "Test Connection", "Home › Add › Data Sources", test).view().params(
r#"{"id"?: "a connection's id or name", "kind"?: "postgres"|"mysql"|"sqlserver"|"service"|"wms"|"wmts"|"wfs"|"wcs"|"ogcapi"|"arcgis"|"csw"|"stac"|"s3", "name"?: text, "group"?: text, "address"?: text, "options"?: "an unsaved connection, as connection.new (when no id)", "password"?: text, "accessKeyId"?: text, "secretAccessKey"?: text, "sessionToken"?: "as connection.login (logs in first)", "probe"?: "true: only the address the test reads, {fetch} (null for databases, which their driver tests)", "answer"?: "non-database kinds only: what that address returned, when the app fetched it (no network request then); databases ignore answer and test through their driver"}"#,
),
C::new("connection.browse", "Browse Connection", "Home › Add › Data Sources", browse::browse).view().params(
r#"{"id": "a connection's id or name", "node"?: "a child's node, as a listing gives it (the connection's top level when absent)", "probe"?: "true: only the address this level reads, {fetch} (null: read without a fetch, or by the database driver); an S3 connection logs in first, as connection.test does", "answer"?: "what that address returned, when the app fetched it", "documents"?: [{"url": "a further document a listing asked for (next)", "text": "its answer"}]} → {connection, node, children: [{key, name, what, detail?, node? (browse it), children? (listed already), add? {command, params}: the command that adds it}], truncated?, matched?, notes?, service? {url, type}, next? (fetch it, then ask again with answer and documents)}"#,
),
]
}

Expand All @@ -53,16 +59,7 @@ fn shown(c: &Connection) -> Value {
} else {
false
};
let add_with = match c.kind.as_str() {
"postgres" | "mysql" | "sqlserver" => "info.databaseTables {database: address}, then layer.addDatabase {database: address, layer}",
"service" => "service.layers {url: address}, then service.add {url, layer}",
"wms" | "wmts" | "wfs" | "ogcapi" | "arcgis" => "service.layers {url: address, type: kind}, then service.add {url, type, layer}",
"wcs" => "service.layers {url: address, type: wcs}, then service.coverage {url, layer}",
"csw" => "catalog.search {url: address, query}",
"stac" => "stac.collections {url: address}, then stac.search {url, collections}",
"s3" => "connection.login {id} once, then s3.list {connection: name}, then layer.addUrl {url: s3://…}",
_ => "",
};
let add_with = "connection.browse {id}, then {id, node} for a child's node; run a dataset's add {command, params}";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit (low confidence): add_with used to be empty for an unknown kind and was per-kind guidance. It's now one string for every kind, and it no longer says that S3 needs connection.login first when credentials are keys. connection.browse does return that hint on error, so this is only a discoverability loss. The per-kind guidance also told the assistant the underlying commands (stac.search, service.coverage), which it can no longer see. Consider keeping a short per-kind hint.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kept as is: the plan asks for one addWith hint for every kind, and connection.browse names the next step itself (its errors say to log in first, and each child carries the command that adds it), so a per-kind list would only repeat what browsing returns.

let mut out = serde_json::to_value(c).unwrap_or(Value::Null);
out["available"] = json!(available);
if !available {
Expand Down
19 changes: 19 additions & 0 deletions crates/engine/src/cmd/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,15 @@ pub(super) fn database_tables(_s: &mut Session, p: &Value) -> CmdResult {
}
}

/// The geometry tables of a live database server, with the schema, name, column and type of
/// each (`connection.browse` groups them by schema).
#[cfg(not(target_arch = "wasm32"))]
pub(super) fn database_table_details(p: &Value) -> Result<Vec<Value>, String> {
let db = database_param(p).ok_or("database is required")?;
let live = LiveDb::connect(&db).ok_or("not a database server")?.map_err(|e| format!("{}: {e}", db.short()))?;
Ok(live.tables().map_err(|e| format!("{}: {e}", db.short()))?.iter().map(LiveTable::detail).collect())
}

/// Adds the tables of a database (a PostgreSQL connection or a DuckDB file) that have a geometry
/// column, or the one `layer` names.
fn add_database(s: &mut Session, p: &Value) -> CmdResult {
Expand Down Expand Up @@ -1399,6 +1408,16 @@ impl LiveTable {
LiveTable::Sqlserver(t) => t.label(),
}
}

/// The table as a browser lists it: its label for `layer.addDatabase`, and what it is made of.
fn detail(&self) -> Value {
let (schema, name, column, kind) = match self {
LiveTable::Postgis(t) => (&t.schema, &t.name, &t.column, &t.kind),
LiveTable::Mysql(t) => (&t.schema, &t.name, &t.column, &t.kind),
LiveTable::Sqlserver(t) => (&t.schema, &t.name, &t.column, &t.kind),
};
json!({"label": self.label(), "schema": schema, "name": name, "column": column, "kind": kind})
}
}

#[cfg(not(target_arch = "wasm32"))]
Expand Down
1 change: 1 addition & 0 deletions crates/engine/src/cmd/plugins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ const NEVER: &[&str] = &[
"connection.remove",
"connection.login",
"connection.test",
"connection.browse",
"s3.connect",
"s3.disconnect",
"earthdata.login",
Expand Down
Loading
Loading