diff --git a/Cargo.lock b/Cargo.lock index 6ce187405e5..96767fb9549 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -631,6 +631,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.1" @@ -899,6 +908,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "ctor" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e" +dependencies = [ + "quote", + "syn 2.0.32", +] + [[package]] name = "data-encoding" version = "2.3.2" @@ -948,7 +967,7 @@ version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case", + "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version", @@ -1811,6 +1830,15 @@ dependencies = [ "url", ] +[[package]] +name = "graph-node-napi" +version = "0.1.0" +dependencies = [ + "graph", + "napi", + "napi-derive", +] + [[package]] name = "graph-runtime-derive" version = "0.33.0" @@ -2643,6 +2671,16 @@ version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +[[package]] +name = "libloading" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +dependencies = [ + "cfg-if 1.0.0", + "windows-sys 0.48.0", +] + [[package]] name = "linux-raw-sys" version = "0.3.1" @@ -2876,6 +2914,57 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +[[package]] +name = "napi" +version = "2.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1133249c46e92da921bafc8aba4912bf84d6c475f7625183772ed2d0844dc3a7" +dependencies = [ + "bitflags 2.4.0", + "ctor", + "napi-derive", + "napi-sys", + "once_cell", +] + +[[package]] +name = "napi-derive" +version = "2.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b5af262f1d8e660742eb722abc7113a5b3c3de4144d0ef23ede2518672ceff1" +dependencies = [ + "cfg-if 1.0.0", + "convert_case 0.6.0", + "napi-derive-backend", + "proc-macro2", + "quote", + "syn 2.0.32", +] + +[[package]] +name = "napi-derive-backend" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea236321b521d6926213a2021e407b0562e28a257c037a45919e414d2cdb4f8" +dependencies = [ + "convert_case 0.6.0", + "once_cell", + "proc-macro2", + "quote", + "regex", + "semver", + "syn 2.0.32", +] + +[[package]] +name = "napi-sys" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2503fa6af34dc83fb74888df8b22afe933b58d37daf7d80424b1c60c68196b8b" +dependencies = [ + "libloading", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -2973,9 +3062,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -5083,6 +5172,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + [[package]] name = "unicode-width" version = "0.1.8" diff --git a/Cargo.toml b/Cargo.toml index 1b49e8b2194..7a3f3504f78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "core", "chain/*", "graphql", + "napi", "node", "runtime/*", "server/*", @@ -38,4 +39,3 @@ incremental = false lto = true opt-level = 's' strip = "debuginfo" - diff --git a/graph/src/schema/input_schema.rs b/graph/src/schema/input_schema.rs index c286f6ed527..13f77c5b56b 100644 --- a/graph/src/schema/input_schema.rs +++ b/graph/src/schema/input_schema.rs @@ -19,7 +19,9 @@ use crate::schema::api::api_schema; use crate::util::intern::{Atom, AtomPool}; use super::fulltext::FulltextDefinition; -use super::{ApiSchema, AsEntityTypeName, EntityType, Schema, SCHEMA_TYPE_NAME}; +use super::{ + ApiSchema, AsEntityTypeName, EntityType, Schema, SchemaValidationError, SCHEMA_TYPE_NAME, +}; /// The name of the PoI entity type pub(crate) const POI_OBJECT: &str = "Poi$"; @@ -465,6 +467,17 @@ impl InputSchema { }) } + pub fn validate(raw: &str, id: DeploymentHash) -> Vec { + let schema = match Schema::parse(raw, id.clone()) { + Ok(schema) => schema, + Err(err) => return vec![SchemaValidationError::InvalidSchema(err.to_string())], + }; + match validations::validate(&schema) { + Ok(_) => vec![], + Err(errors) => errors, + } + } + /// Convenience for tests to construct an `InputSchema` /// /// # Panics diff --git a/graph/src/schema/mod.rs b/graph/src/schema/mod.rs index 80b54ddb22b..1c1be8cd927 100644 --- a/graph/src/schema/mod.rs +++ b/graph/src/schema/mod.rs @@ -52,6 +52,8 @@ impl fmt::Display for Strings { #[derive(Debug, Error, PartialEq, Eq)] pub enum SchemaValidationError { + #[error("Invalid schema: {0}")] + InvalidSchema(String), #[error("Interface `{0}` not defined")] InterfaceUndefined(String), diff --git a/napi/Cargo.toml b/napi/Cargo.toml new file mode 100644 index 00000000000..a4d25c8e86e --- /dev/null +++ b/napi/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "graph-node-napi" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +graph = { path = "../graph" } +napi = "2.14.1" +napi-derive = "2.14.4" diff --git a/napi/src/lib.rs b/napi/src/lib.rs new file mode 100644 index 00000000000..0ab1171aa0e --- /dev/null +++ b/napi/src/lib.rs @@ -0,0 +1,22 @@ +use napi::bindgen_prelude as n; +use napi_derive::napi; + +use graph::{data::subgraph::DeploymentHash, schema::InputSchema}; + +#[napi] +pub fn validate_schema(schema: String, id: String) -> n::Result> { + let id = match DeploymentHash::new(id) { + Ok(id) => id, + Err(e) => { + return Err(n::Error::new( + n::Status::InvalidArg, + format!("Invalid deployment hash {e}"), + )) + } + }; + let errs = InputSchema::validate(&schema, id) + .into_iter() + .map(|e| e.to_string()) + .collect(); + Ok(errs) +}