diff --git a/Cargo.lock b/Cargo.lock index 458078f..83baf29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4649,6 +4649,15 @@ dependencies = [ "tempfile", ] +[[package]] +name = "omnigraph-queries" +version = "0.6.1" +dependencies = [ + "omnigraph-compiler", + "omnigraph-config", + "tempfile", +] + [[package]] name = "omnigraph-server" version = "0.6.1" @@ -4668,6 +4677,7 @@ dependencies = [ "omnigraph-config", "omnigraph-engine", "omnigraph-policy", + "omnigraph-queries", "regex", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 043e67d..b60d6d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "crates/omnigraph-policy", "crates/omnigraph-server", "crates/omnigraph-config", + "crates/omnigraph-queries", ] default-members = [ "crates/omnigraph", diff --git a/crates/omnigraph-queries/Cargo.toml b/crates/omnigraph-queries/Cargo.toml new file mode 100644 index 0000000..6a7a720 --- /dev/null +++ b/crates/omnigraph-queries/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "omnigraph-queries" +version = "0.6.1" +edition = "2024" +description = "Stored-query registry and validation for the Omnigraph graph database." +license = "MIT" +repository = "https://github.com/ModernRelay/omnigraph" +homepage = "https://github.com/ModernRelay/omnigraph" +documentation = "https://docs.rs/omnigraph-queries" + +[dependencies] +omnigraph-config = { path = "../omnigraph-config", version = "0.6.1" } +omnigraph-compiler = { path = "../omnigraph-compiler", version = "0.6.1" } + +[dev-dependencies] +tempfile = { workspace = true } diff --git a/crates/omnigraph-server/src/queries.rs b/crates/omnigraph-queries/src/lib.rs similarity index 90% rename from crates/omnigraph-server/src/queries.rs rename to crates/omnigraph-queries/src/lib.rs index bf131c8..ff93f60 100644 --- a/crates/omnigraph-server/src/queries.rs +++ b/crates/omnigraph-queries/src/lib.rs @@ -22,7 +22,7 @@ use omnigraph_compiler::query::parser::parse_query; use omnigraph_compiler::query::typecheck::typecheck_query_decl; use omnigraph_compiler::types::{PropType, ScalarType}; -use crate::config::{OmnigraphConfig, QueryEntry}; +use omnigraph_config::{OmnigraphConfig, QueryEntry}; /// One loaded stored query. `source` is the full `.gq` file text — the /// invocation handler hands it to `run_query` / `run_mutate` verbatim, @@ -593,71 +593,11 @@ embedding: Vector(4) assert!(report.is_clean(), "no breakage or warning expected: {:?}", report); } - // --- catalog projection (api::query_catalog_entry) --- - - #[test] - fn catalog_entry_projects_every_param_kind() { - use crate::api::{self, ParamKind}; - let reg = QueryRegistry::from_specs(vec![spec_tool( - "all_types", - "query all_types($s: String, $i: I32, $big: I64, $u: U64, $f: F64, $b: Bool, \ - $d: Date, $dt: DateTime, $blob: Blob, $opt: String?, $list: [I32], $vec: Vector(4)) \ - { match { $x: User } return { $x.name } }", - true, - "all", - )]) - .unwrap(); - let entry = api::query_catalog_entry(reg.lookup("all_types").unwrap()); - assert_eq!(entry.name, "all_types"); - assert_eq!(entry.tool_name, "all"); - assert!(!entry.mutation); - - let by: std::collections::HashMap<_, _> = - entry.params.iter().map(|p| (p.name.as_str(), p)).collect(); - assert_eq!(by["s"].kind, ParamKind::String); - assert_eq!(by["i"].kind, ParamKind::Int); - assert_eq!(by["big"].kind, ParamKind::BigInt, "I64 → bigint (string on the wire)"); - assert_eq!(by["u"].kind, ParamKind::BigInt, "U64 → bigint"); - assert_eq!(by["f"].kind, ParamKind::Float); - assert_eq!(by["b"].kind, ParamKind::Bool); - assert_eq!(by["d"].kind, ParamKind::Date); - assert_eq!(by["dt"].kind, ParamKind::DateTime); - assert_eq!(by["blob"].kind, ParamKind::Blob); - assert!(!by["s"].nullable); - assert!(by["opt"].nullable, "String? → nullable"); - assert_eq!(by["list"].kind, ParamKind::List); - assert_eq!(by["list"].item_kind, Some(ParamKind::Int), "[I32] → list of int"); - assert_eq!(by["vec"].kind, ParamKind::Vector); - assert_eq!(by["vec"].vector_dim, Some(4)); - } - - #[test] - fn catalog_entry_flags_mutation_and_empty_params() { - use crate::api; - let reg = QueryRegistry::from_specs(vec![spec( - "add_user", - "query add_user($name: String) { insert User { name: $name } }", - true, - )]) - .unwrap(); - let entry = api::query_catalog_entry(reg.lookup("add_user").unwrap()); - assert!(entry.mutation, "insert body → mutation flag"); - - let reg2 = QueryRegistry::from_specs(vec![spec( - "no_params", - "query no_params() { match { $u: User } return { $u.name } }", - true, - )]) - .unwrap(); - let entry2 = api::query_catalog_entry(reg2.lookup("no_params").unwrap()); - assert!(entry2.params.is_empty(), "no declared params → empty list"); - } - // --- load() error collection (file I/O + parse in one pass) --- #[test] fn load_collects_io_and_parse_errors_in_one_pass() { - use crate::config::load_config; + use omnigraph_config::load_config; let temp = tempfile::tempdir().unwrap(); std::fs::write( temp.path().join("good.gq"), diff --git a/crates/omnigraph-server/Cargo.toml b/crates/omnigraph-server/Cargo.toml index 931e76d..8d4778a 100644 --- a/crates/omnigraph-server/Cargo.toml +++ b/crates/omnigraph-server/Cargo.toml @@ -23,6 +23,7 @@ omnigraph = { package = "omnigraph-engine", path = "../omnigraph", version = "0. omnigraph-compiler = { path = "../omnigraph-compiler", version = "0.6.1" } omnigraph-policy = { path = "../omnigraph-policy", version = "0.6.1" } omnigraph-config = { path = "../omnigraph-config", version = "0.6.1" } +omnigraph-queries = { path = "../omnigraph-queries", version = "0.6.1" } axum = { workspace = true } clap = { workspace = true } color-eyre = { workspace = true } diff --git a/crates/omnigraph-server/src/lib.rs b/crates/omnigraph-server/src/lib.rs index f448471..bd60d96 100644 --- a/crates/omnigraph-server/src/lib.rs +++ b/crates/omnigraph-server/src/lib.rs @@ -4,7 +4,7 @@ pub use omnigraph_config as config; pub mod graph_id; pub mod identity; pub mod policy; -pub mod queries; +pub use omnigraph_queries as queries; pub mod registry; pub mod workload;