protocheck-build 0.1.11

⚙️ Build-time entrypoint for protocheck
Documentation
# ⚒️ Protocheck-build

This is the build-time entrypoint for [protocheck](https://docs.rs/protocheck/0.1.5/protocheck/). 

## ➡️ Getting started 

To get started, you need to use [`protocheck-build`] as a build dependency in your crate, which will use [`protocheck-proc-macro`](https://docs.rs/protocheck-proc-macro/latest/protocheck_proc_macro/index.html) to add all the validation logic to your structs. The setup will look more or less like this (this is taken directly from the [`tests`](https://github.com/Rick-Phoenix/protocheck/tree/main/tests) crate)

```rust
// In your build.rs file
use prost_build::Config;
use protocheck_build::{compile_protos_with_validators, get_proto_files_recursive};
use std::{
  env,
  path::PathBuf
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
  println!("cargo:rerun-if-changed=proto/");

  let out_dir = env::var("OUT_DIR")
    .map(PathBuf::from)
    .unwrap_or(env::temp_dir());

  let descriptor_path = out_dir.join("file_descriptor_set.bin");

  let proto_include_paths = &["proto"];

  // Use the helper to get all proto files recursively in a directory
  let proto_files = get_proto_files_recursive("proto")?;

  let mut config = Config::new();
  config
    .file_descriptor_set_path(&descriptor_path)
    // Enable the use of bytes::Bytes for `bytes` fields
    .bytes(["."])
    .out_dir(&out_dir);

  // Call the build helper
  compile_protos_with_validators(&mut config, &proto_files, proto_include_paths, &["myapp.v1"])?;

  // Compile protos
  config.compile_protos(&proto_files, proto_include_paths)?;

  // Set the env for the file descriptor location
  println!(
    "cargo:rustc-env=PROTO_DESCRIPTOR_SET={}",
    descriptor_path.display()
  );

  Ok(())
}
```

[`compile_protos_with_validators`](https://docs.rs/protocheck-build/0.1.0/protocheck_build/fn.compile_protos_with_validators.html) takes these arguments:

1. The [`config`]https://docs.rs/prost-build/latest/prost_build/struct.Config.html struct.
2. The proto files and include paths being used by the [`config`]https://docs.rs/prost-build/latest/prost_build/struct.Config.html.
3. The list of packages to apply validators to. If a given message contains Cel validation or is validated as a field by another message, its package name must be included in this list.

The function will then:

1. Compile your protos to create an intermediary descriptor
2. Iterate its messages, and use the information extracted from them to add the derives and attributes to the actual [`config`]https://docs.rs/prost-build/latest/prost_build/struct.Config.html that are needed by [`protocheck-proc-macro`]https://docs.rs/protocheck-proc-macro/0.1.0/protocheck_proc_macro/index.html to add the validation logic.
3. Add the derive macros used by `protocheck`
4. Use `proto_types` as the source for the well known types and the protovalidate types (it is re-exported by protocheck, so there is no need to add it as a dependency).

## 🍸 Tonic example

When using [`tonic-prost-build`](https://crates.io/crates/tonic-prost-build), the workflow is almost identical, except that we pass the config to `compile_with_config`:

```rust,ignore
  let mut config = Config::new();
  config
    .file_descriptor_set_path(&descriptor_path)
    .bytes(["."])
    .out_dir(&out_dir);

  // Call the build helper
  compile_protos_with_validators(&mut config, &proto_files, &["proto".to_string()], &["myapp.v1"])?;

  // Compile protos
  tonic_prost_build::configure()
    // We pass the config here
    .compile_with_config(config, &proto_files, &["proto".to_string()])?;
}
```