progit_plugin_sdk/lib.rs
1// SPDX-License-Identifier: LSL-1.0
2// Copyright (c) 2025 Markus Maiwald
3
4//! # ProGit Plugin SDK
5//!
6//! LSL-1.0 licensed SDK for building ProGit plugins in Lua or WASM.
7//!
8//! ## Architecture
9//!
10//! The SDK is the single contract between the ProGit TUI core (LCL-1.0)
11//! and community / commercial plugins. The SDK itself is LSL-1.0 (file-level
12//! copyleft + explicit patent grant) so corporations can ship closed plugins
13//! without license contagion. Modifications to SDK files stay open.
14//!
15//! ## Plugin Types
16//!
17//! - **Lua Plugins** — lightweight scripting via LuaJIT, sandboxed by default.
18//! - **WASM Plugins** — high-performance compiled plugins, available behind
19//! the `wasm` feature flag. Off by default to keep the binary lean.
20//!
21//! ## v0.2 Highlights
22//!
23//! - One canonical [`event::PluginEvent`] enum (host no longer redefines it).
24//! - LuaJIT runtime is sandboxed: dangerous stdlib (`os.execute`, `io.popen`,
25//! `package.loadlib`, `debug`) is dropped by default.
26//! - Per-plugin memory limits and instruction caps via [`lua::LuaPluginOptions`].
27//! - Injected `log` and `storage` globals so plugins do not have to invent
28//! their own logging or persistence.
29//! - Per-plugin failure isolation with quarantine after N consecutive errors.
30//! - SDK API versioning + capability declarations on the plugin metadata.
31//!
32//! ## Example
33//!
34//! ```rust,ignore
35//! use progit_plugin_sdk::prelude::*;
36//!
37//! let mut plugin = LuaPlugin::load("plugins/my-plugin.lua")?;
38//! let context = PluginContext {
39//! repo_path: "/path/to/repo".into(),
40//! user: Some("developer".into()),
41//! env: Default::default(),
42//! config: Default::default(),
43//! };
44//! plugin.init(&context)?;
45//!
46//! if plugin.supports_hook(&PluginHook::OnIssueCreated) {
47//! let data = serde_json::json!({"id": "123", "title": "Bug fix"});
48//! plugin.execute_hook(&PluginHook::OnIssueCreated, &data)?;
49//! }
50//! # Ok::<(), anyhow::Error>(())
51//! ```
52
53pub mod contributions;
54pub mod event;
55pub mod lua;
56pub mod manifest;
57pub mod render;
58pub mod storage;
59pub mod traits;
60
61#[cfg(feature = "wasm")]
62pub mod wasm;
63
64pub mod prelude {
65 //! Convenience re-exports for plugin development.
66
67 pub use crate::contributions::{
68 CommandArgs, CommandContribution, CommandOutputMode, CommandTuiContribution,
69 PluginContributionManifest, PluginContributions,
70 };
71 pub use crate::event::{PipelineJob, PipelineState, PipelineStatus, PluginEvent};
72 pub use crate::lua::{
73 LuaPlugin, LuaPluginOptions, SoberHost, SoberInvocation, SoberInvocationResult,
74 };
75 pub use crate::manifest::{Capabilities, PluginManifest, SdkVersion};
76 pub use crate::render::{HighlightRequest, HighlightResponse, Rgb, TokenSpan};
77 pub use crate::storage::{JsonFileStorage, PluginStorage, SyncState};
78 pub use crate::traits::*;
79
80 #[cfg(feature = "wasm")]
81 pub use crate::wasm::WasmPlugin;
82}
83
84/// Plugin SDK semantic version (taken from `Cargo.toml` at build time).
85pub const VERSION: &str = env!("CARGO_PKG_VERSION");
86
87/// SDK API contract version. Plugins declare a compatible version in their
88/// metadata; the loader rejects plugins with a mismatched major.
89///
90/// Bump the **major** when an existing API method signature or hook payload
91/// shape changes in a breaking way. Bump the **minor** when adding new
92/// hooks, events, or stdlib globals.
93pub const SDK_API_VERSION: &str = "0.3";
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn version_constants_are_set() {
101 assert!(!VERSION.is_empty());
102 assert!(SDK_API_VERSION.starts_with("0."));
103 }
104}