cordis-include 0.0.9

Config entry trees and YAML/JSON loader files for the cordis-rs plugin framework
Documentation

cordis-include

Config entry trees and YAML/JSON loader files for the cordis-rs plugin framework.

This crate is the data half of porting upstream Cordis' loader: it maps between config files on disk and an in-memory tree of entries, preserving object key order for diff-friendly files, expanding ${{ env.NAME }} templates, and providing the suspend guards that break the write → watch → write feedback loop.

┌─ cordis-loader   assembly: plugin registry + fiber state machine
├─ cordis-group    group plugin (nesting marker)
├─ cordis-include  ← this crate: entry trees + config files
└─ cordis-rs       core runtime (zero dependencies)

Example

use cordis_include::{Entry, EntryOptions, EntryTree, Node};
# fn main() -> cordis_include::Result<()> {
let tree = EntryTree::new();

// Load a set of entries (from a file, or built by hand).
let diff = tree.update(vec![
    EntryOptions::new("group").with_id("srv").with_group(vec![
        EntryOptions::new("adapter-http").with_config(
            [("port".to_string(), Node::Int(8080))].into_iter().collect(),
        ),
    ]),
])?;
assert_eq!(diff.created.len(), 2);

// A full reload matches entries by id across groups: existing entry
// objects are reused (same pointer), so callers can keep their handles.
let kept = tree.resolve("srv").unwrap();
tree.update(vec![EntryOptions::new("group").with_id("srv")])?;
assert!(Entry::ptr_eq(&kept, &tree.resolve("srv").unwrap()));
# Ok(())
# }

Files round-trip through LoaderFile with atomic .tmp + rename writes, readonly detection, unknown top-level keys preserved, and coalesced deferred writes (write_deferred) for bursty callers:

entries:
  - id: srv
    name: group
    group:
      - name: adapter-http
        config:
          port: 8080
          host: ${{ env.HOST }}

Feature flags

  • watch — debounced file watching through notify. Events observed while the file is suspended (our own writes, or reloads in progress) do not fire the callback.

Scope

This crate deliberately knows nothing about where plugins come from and never starts or stops fibers: cordis-loader implements the PluginResolver contract defined here and drives the lifecycle.