# razeri-plugin-api
Extension traits and registries for building [Razeri](https://github.com/gaoash/razeri) plugins.
This is the **single crate** third-party authors depend on to extend Razeri with new database dialects, storage backends, LLM providers, AI model adapters, language renderers, and event sinks.
## Extension Points
| `PlatformDialect` | `PlatformRegistry` | SQL dialect for a new database |
| `StorageProviderFactory` | `StorageRegistry` | Storage backend (S3, Azure, etc.) |
| `LlmClientFactory` | `LlmRegistry` | LLM provider (Ollama, OpenAI, etc.) |
| `LlmModelAdapter` | `ModelRegistry` | Model capabilities and routing |
| `LanguageRendererFactory` | `LanguageRegistry` | Code generation target language |
| `EventSink` | `EventRegistry` | Structured telemetry sink |
The rendering traits themselves live in
[`razeri-plugin-contract`](https://crates.io/crates/razeri-plugin-contract),
which this crate depends on and re-exports as `razeri_plugin_api::razeri_plugin_contract`.
## Quick Start
```rust
use std::sync::Arc;
use razeri_plugin_api::builder::DialectRegistration;
use razeri_plugin_api::dialect::{DialectInfo, PlatformDialect};
use razeri_plugin_api::razeri_plugin_contract::{
render_data_type_ansi, DataType, DdlRenderer, DialectCapabilities,
DialectFamily, DmlRenderer, ExpressionRenderer, FormulaRenderer,
ProcedureRenderer, ReplicationRenderer, SqlRenderer, StorageRenderer,
TaskRenderer,
};
struct MyDialect;
// SqlRenderer: 4 required methods; everything else defaults to ANSI behaviour.
impl SqlRenderer for MyDialect {
fn render_data_type(&self, dt: &DataType) -> String { render_data_type_ansi(dt) }
fn quote_identifier(&self, name: &str) -> String { format!("\"{name}\"") }
fn qualify_name(&self, schema: Option<&str>, name: &str) -> String {
match schema {
Some(s) => format!("{s}.{name}"),
None => name.to_string(),
}
}
fn render_current_timestamp(&self) -> String { "CURRENT_TIMESTAMP".into() }
}
// Remaining traits: all methods have defaults — each override is a decision
// your engine states about itself.
impl ExpressionRenderer for MyDialect {}
impl DdlRenderer for MyDialect {}
impl DmlRenderer for MyDialect {}
impl ProcedureRenderer for MyDialect {}
impl FormulaRenderer for MyDialect {}
impl TaskRenderer for MyDialect {}
impl ReplicationRenderer for MyDialect {}
impl StorageRenderer for MyDialect {}
impl DialectCapabilities for MyDialect {}
impl PlatformDialect for MyDialect {
fn info(&self) -> DialectInfo {
DialectInfo {
name: "my-database",
display_name: "My Database",
// The other spellings a design may use for this platform.
aliases: &["mydb"],
dialect_family: DialectFamily::Custom("my-database"),
family: "My Database SQL",
is_cloud_native: false,
is_olap: false,
is_postgres_compatible: false,
}
}
}
// Auto-register at link time
inventory::submit! {
DialectRegistration::new("my-database", || Arc::new(MyDialect))
}
```
## Proving a plugin
The conformance kit runs from your own test suite and grades the plugin the
way Razeri grades its shipped dialects — defaulted decisions, contradictory
capability answers, missing refusal wording:
```rust
let report = razeri_plugin_api::conformance::check(&MyDialect);
assert!(report.is_clean(), "{report}");
```
Your dialect's names are yours: `name` is the one Razeri reports, `aliases` is
every other spelling a design may use for the same platform, and the resolver
reads both off the dialects that are loaded. A clean report never depends on
anything inside Razeri — only on not claiming a spelling another loaded platform
already answers to.
## Stability
This crate and `razeri-plugin-contract` follow semantic versioning while
the major version is zero. A trait gains a method only with a default body,
so an existing plugin keeps compiling across a minor release without
changing a line. A method that leaves does so as `#[deprecated]` for one
minor version before it is removed, so a plugin sees the warning before the
removal, not after.
## Features
- **`dynamic`** (default) — Enables runtime plugin loading via shared libraries (`libloading`).
## Documentation
- [Plugin Authoring Guide](https://gaoash.github.io/razeri/plugins/authoring-guide.html)
- [Plugin Architecture Overview](https://gaoash.github.io/razeri/plugins/overview.html)
- [API Reference](https://gaoash.github.io/razeri/rustdoc/razeri_plugin_api/)
## License
Dual-licensed under [MIT](LICENSE-MIT) or [Apache 2.0](LICENSE-APACHE), at
your option — this crate is the open surface of an otherwise proprietary
workspace, so plugin authors depend on it freely. The rest of the
[Razeri repository](https://github.com/gaoash/razeri) is covered by its root
`LICENSE` (see its §4, "Plugins are open").
## Security
Report a vulnerability through [GitHub's private vulnerability reporting](https://github.com/gaoash/razeri/security/advisories/new) on the Razeri repository — see its [security policy](https://github.com/gaoash/razeri/blob/main/SECURITY.md).