Skip to main content

cli/
extensions.rs

1// SPDX-License-Identifier: Apache-2.0
2//! Local glue between cli's dispatch and the `WeftExtensions`
3//! trait surface.
4//!
5//! In OSS builds without the `client` feature, `main.rs` constructs a
6//! `NoopWeftExtensions` from the shim crate directly. With
7//! `client` enabled, this module provides
8//! [`EnabledWeftExtensions`], which downcasts the trait's opaque
9//! arguments back to `cli::cli::AuthCommands` and delegates to the
10//! hosted client implementation.
11//!
12//! Step 5 of the OSS extraction plan moves the underlying command
13//! implementations out of `cli` into a separate `client`
14//! crate that ships the closed build. At that point this adapter goes
15//! away and the closed crate implements `WeftExtensions` directly.
16
17#![cfg(feature = "client")]
18
19use std::any::Any;
20
21use anyhow::{Result, anyhow};
22use async_trait::async_trait;
23use weft_client_shim::{CliContext, WeftExtensions};
24
25use crate::cli::{AuthCommands, commands::cmd_auth};
26
27pub struct EnabledWeftExtensions;
28
29#[async_trait]
30impl WeftExtensions for EnabledWeftExtensions {
31    async fn auth(
32        &self,
33        ctx: &(dyn CliContext + 'static),
34        command: &(dyn Any + Send + Sync),
35    ) -> Result<()> {
36        let command = downcast::<AuthCommands>(command, "AuthCommands")?;
37        cmd_auth(ctx, command.clone().into()).await
38    }
39
40    async fn whoami(
41        &self,
42        ctx: &(dyn CliContext + 'static),
43        server: Option<String>,
44    ) -> Result<()> {
45        heddle_client::cmd_whoami(ctx, server).await
46    }
47}
48
49fn downcast<'a, T: 'static>(
50    value: &'a (dyn Any + Send + Sync),
51    name: &'static str,
52) -> Result<&'a T> {
53    value
54        .downcast_ref::<T>()
55        .ok_or_else(|| anyhow!("WeftExtensions trait dispatch: failed to downcast to {name}"))
56}