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 | |
| 27 | use crate::srv::{ |
| 28 | api::ApiHandler, |
| 29 | webhook::WebhookHandler, |
| 30 | }; |
| 31 | |
| 32 | use oxedyne_fe2o3_core::prelude::*; |
| 33 | use oxedyne_fe2o3_syntax::{ |
| 34 | Syntax, |
| 35 | msg::MsgCmd, |
| 36 | }; |
| 37 | use 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. |
| 48 | pub 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 | |
| 87 | pub struct NoExtension; |
| 88 | |
| 89 | impl AppExtension for NoExtension {} |