Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_steel/src/app/ext.rs

3.5 KiB, 24 runs

created by r1870400018:10093, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1//! [Written with AI entirely](https://need2know.ai/entirely-ai/code)\
2//! Anthropic Claude
3
4/// App extension surface.
5///
6/// Steel is a server framework used by concrete applications. Each
7/// app may need:
8///
9/// * its own shell subcommands (with proper `help`/`cat`/args in
10/// the Syntax tree so `./steel help` lists them alongside the
11/// built-ins).
12/// * its own webhook handlers (incoming notifications from third
13/// parties -- already covered by `srv::webhook::WebhookRegistry`).
14/// * its own API handlers (in-process request handlers mounted at
15/// `api_routes` paths that are marked with a `handler` name
16/// instead of being proxied to a remote upstream).
17///
18/// This module defines a single trait, `AppExtension`, that app
19/// binaries implement and hand to `run_with_extension`. Steel then
20/// uses it to populate the shell Syntax tree, to build the webhook
21/// and API registries at startup, and to dispatch shell commands it
22/// does not recognise.
23///
24/// Steel binaries that do not need any extension can pass
25/// `NoExtension`, which is the default handed to `run`.
26
27use crate::srv::{
28 api::ApiHandler,
29 webhook::WebhookHandler,
30};
31
32use oxedyne_fe2o3_core::prelude::*;
33use oxedyne_fe2o3_syntax::{
34 Syntax,
35 msg::MsgCmd,
36};
37use oxedyne_fe2o3_tui::lib_tui::repl::{
38 Evaluation,
39 ShellConfig,
40};
41
42
43// ┌───────────────────────────────────────────────────────────────────────────┐
44// │ APP EXTENSION TRAIT │
45// └───────────────────────────────────────────────────────────────────────────┘
46
47/// Extension surface an app binary hands to Steel at startup.
48pub trait AppExtension: Send + Sync + 'static {
49
50 /// Called once at shell startup, after Steel's own built-ins are in place.
51 fn extend_syntax(&self, s: Syntax) -> Outcome<Syntax> {
52 Ok(s)
53 }
54
55 /// Called when a parsed command name matches no built-in. `Ok(None)` means
56 /// the extension does not own the command.
57 fn dispatch_cmd(
58 &self,
59 _cmd_name: &str,
60 _cmd: &MsgCmd,
61 _shell_cfg: &ShellConfig,
62 )
63 -> Outcome<Option<Evaluation>>
64 {
65 Ok(None)
66 }
67
68 /// Each `(name, handler)` pair is reached by the `handler` name in a
69 /// `webhook_routes` entry.
70 fn webhook_handlers(&self) -> Vec<(String, Box<dyn WebhookHandler>)> {
71 Vec::new()
72 }
73
74 /// Each `(name, handler)` pair is reached by the `handler` name in an
75 /// `api_routes` entry, which dispatches in process instead of proxying to
76 /// `upstream`.
77 fn api_handlers(&self) -> Vec<(String, Box<dyn ApiHandler>)> {
78 Vec::new()
79 }
80}
81
82
83// ┌───────────────────────────────────────────────────────────────────────────┐
84// │ NO-OP EXTENSION │
85// └───────────────────────────────────────────────────────────────────────────┘
86
87pub struct NoExtension;
88
89impl AppExtension for NoExtension {}