Expand description
Cordis is a context-based plugin framework with scoped dependency injection, lifecycle-owned effects, events, configuration interception, and structured logging.
This crate is a Rust port of @deepseek-ai/cordis 4.x. The JavaScript
implementation relies heavily on proxies, prototype chains, callable
objects, and decorators. The Rust API keeps the same runtime model while
replacing those language features with explicit, typed methods.
Naming note: the package is published as cordis-rs, but the library
name and import path are cordis (matching upstream), and the sources
live under crates/cordis in the repository.
§Quick start
use cordis::{plugin_sync, Context, Inject, PluginOutput};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
let root = Context::new();
let counter = Arc::new(AtomicUsize::new(0));
let _counter_effect = root.provide_arc("counter", counter.clone()).unwrap();
let greeter = plugin_sync::<(), _>("greeter", Inject::new(["counter"]),
|ctx, _config| {
let counter = ctx.require::<AtomicUsize>("counter")?;
counter.fetch_add(1, Ordering::SeqCst);
Ok(PluginOutput::default())
});
let fiber = root.plugin(greeter, ());
fiber.try_wait().unwrap();
assert_eq!(counter.load(Ordering::SeqCst), 1);
fiber.dispose().unwrap();§Naming vocabulary
The API keeps upstream Cordis verbs (emit, bail, waterfall,
serial, parallel, on, once, provide, get, set, inject,
isolate, intercept, effect, plugin, accessor, require,
notify) and renames them only when a Rust convention conflicts
strongly (e.g. Event::call_next instead of upstream’s next(), which
collides with Iterator::next). The
suffix/prefix conventions:
*_value— type-erased (Value/Config) variant;resolved_*— evaluated (as opposed to static) result;with_*— builder or “with extra parameter” variant;*Service— context-bound service facade.is_/has_— predicates;assert_— panics (fallible checks areensure_, e.g.Fiber::ensure_active);*_uncheckedis reserved for genuinelyunsafeAPIs (this crate has none).as_— cheap borrow;to_— expensive copy;into_— ownership transfer._asyncsuffixes mark genuinely suspending functions. The one exception isFiber::dispose_async, kept for upstream parity withdisposeAsync: it is a synchronous pass-through that never yields.
§Intercept meta-events
The five upstream interception points are ported as ordinary events on
the root bus, named internal/get, internal/set, internal/config,
internal/update, and internal/listener. Each fires with the operating
context as its dispatch target, so context filters apply, and arguments
are immutable Values — interception means wrapping or vetoing, never
in-place mutation:
internal/get— waterfall around every strict service read (ReflectService::get_value/Context::require); accessor reads and relaxed reads bypass it. The innermost behavior resolves the service; listeners may wrap or replace the result.internal/set— waterfall around service writes (ReflectService::set_value); listeners may veto a write by not callingEvent::call_next.internal/config— waterfall around config resolution (Fiber::updateand activation); the effective config is the waterfall’s result, the original when untouched.internal/update— waterfall around the restart an update schedules; skippingEvent::call_nextvetoes the restart (the config is stored either way).internal/listener— bail fired before a listener is registered; a bail value cancels the registration and the caller receives an inertEffectHandle.
Like upstream, the interception events themselves fire no
internal/dispatch meta-event, so meta-listeners cannot recurse through
them.
Re-exports§
pub use context::Context;pub use context::ContextMeta;pub use context::Isolation;pub use effect::AsyncDisposer;pub use effect::EffectHandle;pub use effect::EffectMeta;pub use error::CordisError;pub use error::ErrorCode;pub use error::Result;pub use error::ValidationError;pub use error::ValidationIssue;pub use events::DispatchMode;pub use events::Event;pub use events::EventOptions;pub use events::EventResult;pub use events::EventValue;pub use events::EventsService;pub use events::is_bailed;pub use fiber::Fiber;pub use fiber::FiberState;pub use logger::ANSI16_PALETTE;pub use logger::ANSI256_PALETTE;pub use logger::Exporter;pub use logger::ExporterConfig;pub use logger::FormatterFn;pub use logger::LogArg;pub use logger::LogKind;pub use logger::Logger;pub use logger::LoggerIntercept;pub use logger::LoggerLevel;pub use logger::LoggerService;pub use logger::Message;pub use logger::color_code;pub use logger::default_format;pub use reflect::Accessor;pub use reflect::Property;pub use reflect::ReflectService;pub use reflect::ServiceInfo;pub use registry::Inject;pub use registry::IntoPlugin;pub use registry::Plugin;pub use registry::PluginHandle;pub use registry::PluginKey;pub use registry::PluginOutput;pub use registry::RegistryService;pub use registry::RuntimeInfo;pub use registry::plugin_async;pub use registry::plugin_sync;pub use service::Service;pub use service::service_async;pub use service::service_sync;pub use value::Config;pub use value::Value;
Modules§
- context
- Root and child contexts tying all Cordis services together.
- effect
- Lifecycle-owned effects and single-shot asynchronous disposers.
- error
- Framework errors and configuration validation diagnostics.
- events
- Disposal-aware event bus and Cordis dispatch strategies.
- fiber
- Plugin fiber lifecycle, dependency epochs, and effect cleanup.
- logger
- Structured logger facade, bounded buffer, formatting, and exporters.
- reflect
- Scoped service storage and explicit reflection APIs.
- registry
- Plugin entrypoints, dependency declarations, and runtime registry.
- service
- Typed service conventions and helpers.
- utils
- Runtime-agnostic future execution.
- value
- Cloneable, dynamically typed values used for services, events, and config.
Constants§
- VERSION
- Version of the cordis-rs core this binary was compiled against.