How to write spec files
The generator is mostly* compliant with the AsyncAPI specification
*Limitations
- Only json payloads are currently supported for automatic deserialization
- Only one server is currently supported and only nats protocol is supported
- Generated microservice doesn't support authentication with NATS-broker out of the box
- Only one message is currently supported per channel, payloads can be choosen freely including anyOf/oneOf/allOf
- The generated rust types are required by default, if you want to use optional types, please modify the generated types after generation or use oneOf/anyOf/allOf to represent optional types
- references in the specification are only suppported inside the same file, external references are not supported
Crustagen specific features
- A channel supposed to be a stream can be declared in the specification file with the
x-streamname
field.
channels:
{channel-name}:
{channel-operation}:
bindings:
nats:
x-streamname: testStream
Writing your own templates
- Any templates that in the templates folder at compilation time will be embedded in the compiled binary.
- If you only have the binary you can put templates in the folder
user-templates
. If a file from theuser-templates
folder has the same path as an embedded template, only the template fromuser-template
will be rendered.- set the command line argument
--user-templates
or-u
to set a custom folder
- set the command line argument
- the last file extension will be removed e.g:
file.rs.go
will be rendered tofile.rs
. - For examples refer to the allready included templates
What fields are available inside templates?
Any of these fields will be accessible:
pub struct TemplateContext<'a> {
pub title: &'a String,
pub description: &'a Option<String>,
pub server: &'a Server,
pub subscribe_channels: Vec<(&'a String, SimplifiedOperation)>,
pub publish_channels: Vec<(&'a String, SimplifiedOperation)>,
pub model: Model,
}
pub struct Model {
pub message_models: Vec<RustSchemaRepresentation>,
// pub enums: Vec<MultiStructEnum>,
}
pub struct SimplifiedOperation {
pub unique_id: String,
pub original_operation: Operation,
// array, da es eine oder mehrere messages geben kann
pub messages: Vec<SimplifiedMessage>,
// pub multiple_messages_enum: Option<MultiStructEnum>,
}
pub struct MultiStructEnum {
pub unique_id: String,
pub messages: Vec<SimplifiedMessage>,
pub struct_definition: String,
}
pub struct SimplifiedMessage {
pub unique_id: String,
pub original_message: Message,
pub payload: Option<RustSchemaRepresentation>,
}
- for more information about the fields available from these structs please refer to: all rust structs
Render to separate files
It is possible to generate files for each specific object in your AsyncAPI documentation. For example, you can specify a filename like $$handler$$.rs.go
to generate a file for each publish_channel
defined in your AsyncAPI spec.
This works with file templates that include the following in their name:
$$handler$$
$$producer$$
$$model$$
$$schemas$$
Functions available inside the templates
to_lower(input: String) -> String
converts String to lowercasekey_exists(input: String) -> String
checks if key existscamel_to_snake_case(input :String) -> String
converts a String in camelCase to snake_casereplace(input: String, from: String, to: String) -> String
replacesfrom
withto
forinput
- Side Note: these functions are defined in
src/generator/template_functions.rs
feel free to extend then, if you have access to the source code.
- Side Note: these functions are defined in
Environment Variables
An .env
-file is automatically generated from the .env template
If you want to extend the .env file feel free to do so in the generated code
- or if you want to customize the generated .enf file before it is generated take a look at writing your own templates The generated microservice uses the following environment variables (with their respective default values):
SERVICE_PORT = "8080"
SERVER_URL = "{{ .server.url }}"
LOG_LEVEL = "DEBUG" # available levels are ERROR, WARN, INFO, DEBUG and TRACE
OPA_RULES= "path/to/admin/policy"
TRACING_ENABLED = false
SCHEMA_VALIDATION_ENABLED = true
Also per channel the subject will be set via an environment variable:
{channel_name}_SUBJECT = "{subject}" # for normal pub_sub channels
{channel_name}_QUEUE = "{subject}" # for nats queue channels
{channel_name}_STREAM = "{subject}" # for nats jetstream channels
And for OPA
OPA_ENABLED = false # choose if OPA should be enabled
#OPA_REMOTE_URL = "localhost:4042" # pick the url for an opa server
#OPA_LOCAL_WASM_PATH = "some/path" # pick the path of a to wasm compiled rego file
- for more information see Working with Open Policy Agent
Working with Open Policy Agent
The microservice can utilize the function:
pub async fn opa_eval<I>(input: Serialize) -> Result<serde_json::Value>
from src/policy/policy.rs
which sends the input
to an opa_server or uses it as input to evaluate a to .wasm
compiled .rego
file dependant on the set enviornment variables.