| Crates.io | marty_plugin_protocol |
| lib.rs | marty_plugin_protocol |
| version | 0.3.0 |
| created_at | 2025-10-02 20:25:42.597143+00 |
| updated_at | 2025-10-02 20:25:42.597143+00 |
| description | Protocol definitions for Marty workspace provider plugins |
| homepage | https://github.com/codyspate/marty |
| repository | https://github.com/codyspate/marty |
| max_upload_size | |
| id | 1865017 |
| size | 80,882 |
The official SDK for creating Marty workspace plugins as dynamic libraries. This crate provides everything you need to build plugins that automatically discover and manage projects within monorepos.
# Cargo.toml
[package]
name = "marty-plugin-myframework"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"] # Required for dynamic library
[dependencies]
marty_plugin_protocol = "0.2"
serde_json = "1.0"
use marty_plugin_protocol::{
dylib::export_plugin, InferredProject, MartyPlugin, Workspace, WorkspaceProvider,
};
use serde_json::{json, Value as JsonValue};
use std::path::Path;
// Define your plugin
pub struct MyFrameworkPlugin;
impl MyFrameworkPlugin {
pub const fn new() -> Self { Self }
}
impl Default for MyFrameworkPlugin {
fn default() -> Self { Self::new() }
}
// Define project detection logic
pub struct MyFrameworkWorkspaceProvider;
impl WorkspaceProvider for MyFrameworkWorkspaceProvider {
fn include_path_globs(&self) -> Vec<String> {
vec!["**/my-framework.json".to_string()]
}
fn exclude_path_globs(&self) -> Vec<String> {
vec!["**/node_modules/**".to_string()]
}
fn on_file_found(&self, _workspace: &Workspace, path: &Path) -> Option<InferredProject> {
if path.file_name()?.to_str()? != "my-framework.json" {
return None;
}
let project_dir = path.parent()?.to_path_buf();
let name = project_dir.file_name()?.to_str()?.to_string();
Some(InferredProject {
name,
project_dir,
discovered_by: "my-framework".to_string(),
workspace_dependencies: Vec::new(), // Parse from config file
})
}
}
// Connect plugin to workspace provider
impl MartyPlugin for MyFrameworkPlugin {
fn name(&self) -> &str { "My Framework Plugin" }
fn key(&self) -> &str { "my-framework" }
fn workspace_provider(&self) -> &dyn WorkspaceProvider {
&MyFrameworkWorkspaceProvider
}
}
// Export for dynamic loading
export_plugin!(MyFrameworkPlugin);
# Build the plugin
cargo build --lib --release
# Install to Marty's plugin directory
cp target/release/libmarty_plugin_myframework.so ~/.marty/plugins/
include_path_globs() patternsexclude_path_globs() are skippedon_file_found() is called for each matching fileInferredProject instancesCritical: workspace_dependencies represents dependencies between projects within the same workspace, NOT external packages.
// โ
CORRECT: Internal workspace projects
vec![
"shared-utils".to_string(), // Another project in workspace
"common-types".to_string(), // Internal dependency
]
// โ INCORRECT: External packages
vec![
"serde".to_string(), // External crate
"lodash".to_string(), // External npm package
]
This is used for:
[dependencies]
shared-utils = { path = "../shared-utils" } # โ
Include "shared-utils"
serde = "1.0" # โ External - ignore
{
"dependencies": {
"@myorg/shared": "workspace:*", // โ
Include "shared"
"@myorg/utils": "file:../utils", // โ
Include "utils"
"lodash": "^4.17.21" // โ External - ignore
}
}
[tool.poetry.dependencies]
shared-lib = { path = "../shared-lib" } # โ
Include "shared-lib"
requests = "^2.25.0" # โ External - ignore
MartyPlugin: Main plugin interface with metadata and configurationWorkspaceProvider: Project discovery and analysis logicInferredProject: Represents a discovered projectWorkspace: Context passed to plugins (root path, existing projects)Project: Explicit projects with marty.yml filesThe export_plugin! macro generates C ABI functions for cross-language compatibility:
plugin_name() - Plugin display nameplugin_key() - Unique identifierplugin_on_file_found() - Project detectionplugin_cleanup_string() - Memory management#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn test_project_detection() {
let provider = MyFrameworkWorkspaceProvider;
let workspace = Workspace {
root: PathBuf::from("/workspace"),
projects: vec![],
inferred_projects: vec![],
};
let path = PathBuf::from("/workspace/project/my-framework.json");
let result = provider.on_file_found(&workspace, &path);
assert!(result.is_some());
let project = result.unwrap();
assert_eq!(project.name, "project");
assert_eq!(project.discovered_by, "my-framework");
}
}
exclude_path_globs()If you're migrating from WASM plugins:
# OLD: WASM target
# [lib]
# crate-type = ["cdylib"]
# [dependencies]
# serde = { version = "1.0", default-features = false }
# NEW: Dynamic library
[lib]
crate-type = ["cdylib"]
[dependencies]
serde_json = "1.0" # Full crate ecosystem available!
// OLD: Manual WASM exports
// #[no_mangle]
// pub extern "C" fn _start() { /* ... */ }
// NEW: Simple macro
export_plugin!(MyPlugin);
Plugin not detected:
crate-type = ["cdylib"] in Cargo.toml~/.marty/plugins/ directoryexport_plugin!(YourPlugin) is calledProjects not discovered:
include_path_globs() patterns match your fileson_file_found() returns Some(InferredProject) for valid projectsBuild errors:
pub const fn new() -> SelfMartyPlugin traitexport_plugin from marty_plugin_protocol::dylibContributions are welcome! Please see the main repository for contributing guidelines.
Licensed under either of Apache License, Version 2.0 or MIT License at your option.
Built by the Marty team ๐ GitHub | Documentation