use crate::prelude::*;
use beet_core::prelude::*;
use beet_flow::prelude::*;
use beet_net::prelude::*;
use beet_router::prelude::*;
pub fn beet_cli() -> impl Bundle {
(
Name::new("Cli Router"),
CliServer,
ExchangeSpawner::new_flow(|| {
(
beet_site_cargo_build_cmd(),
Fallback,
children![
help_handler(HelpHandlerConfig {
introduction: String::from("🌱 Beet CLI 🌱"),
match_root: true,
..default()
}),
EndpointBuilder::new(|| { StatusCode::ImATeapot })
.with_path("teapot")
.with_description("I'm a teapot"),
EndpointBuilder::default()
.with_path("run-wasm/*binary-path")
.with_description("Run a wasm binary")
.with_handler_bundle(run_wasm()),
EndpointBuilder::get()
.with_path("watch/*cmd?")
.with_description(
"Watch for file changes and run command"
)
.with_handler_bundle(watch()),
EndpointBuilder::get()
.with_path("refresh-sst")
.with_description("Refresh SST configuration")
.with_handler_bundle(SstCommand::new(
SstSubcommand::Refresh
)),
EndpointBuilder::get()
.with_path("deploy-sst")
.with_description("Deploy using SST")
.with_handler_bundle(SstCommand::new(
SstSubcommand::Deploy
)),
EndpointBuilder::get()
.with_path("build-wasm")
.with_description("Build wasm target")
.with_handler_bundle(build_wasm()),
EndpointBuilder::get()
.with_path("build-lambda")
.with_description("Compile lambda function")
.with_handler_bundle(CompileLambda),
EndpointBuilder::get()
.with_path("deploy-lambda")
.with_description("Deploy lambda function")
.with_handler_bundle(DeployLambda),
EndpointBuilder::get()
.with_path("watch-lambda")
.with_description("Watch lambda logs")
.with_handler_bundle(WatchLambda),
EndpointBuilder::get()
.with_path("push-assets")
.with_description("Push assets to remote")
.with_handler_bundle(PushAssets),
EndpointBuilder::get()
.with_path("pull-assets")
.with_description("Pull assets from remote")
.with_handler_bundle(PullAssets),
EndpointBuilder::get()
.with_path("push-html")
.with_description("Push HTML to remote")
.with_handler_bundle(PushHtml),
EndpointBuilder::get()
.with_path("build")
.with_description("Build server")
.with_handler_bundle(BuildServer),
EndpointBuilder::get()
.with_path("parse-files")
.with_description("Import and parse source files")
.with_handler_bundle(import_and_parse_source_files()),
EndpointBuilder::get()
.with_path("parse-source-files")
.with_description(
"Parse source files with file watching"
)
.with_handler_bundle((Sequence, children![
import_source_files(),
(
Name::new("Run Loop"),
InsertOn::<GetOutcome, _>::new(
FsWatcher::default_cargo()
),
RunOnDirEvent,
InfallibleSequence,
children![
ParseSourceFiles::action(),
(
Name::new("Full Rebuild Check"),
Sequence,
children![
FileExprChanged::new(),
(
Name::new("Pretend Rebuild.."),
EndWith(Outcome::Pass)
)
]
),
(
Name::new("Pretend Serve..")
),
]
),
])),
EndpointBuilder::get()
.with_path("run")
.with_description("Run the server with file watching")
.with_handler_bundle((Sequence, children![
import_source_files(),
(
Name::new("Run Loop"),
InsertOn::<GetOutcome, _>::new(
FsWatcher::default_cargo()
),
RunOnDirEvent,
InfallibleSequence,
children![
ParseSourceFiles::action(),
(
Name::new("Build Check"),
Sequence,
children![
FileExprChanged::new(),
build_wasm(),
BuildServer,
]
),
ExportStaticContent,
RunServer,
]
),
])),
EndpointBuilder::get()
.with_path("serve")
.with_description("Build and serve the application")
.with_handler_bundle((
Name::new("Serve"),
Sequence,
children![
BuildServer,
ExportStaticContent,
RunServer,
]
)),
EndpointBuilder::get()
.with_path("deploy")
.with_params::<StageParams>()
.with_description("Full deployment pipeline")
.with_handler_bundle((Sequence, children![
import_and_parse_source_files(),
apply_deploy_config(),
build_wasm(),
BuildServer,
ExportStaticContent,
CompileLambda,
PushAssets,
PushHtml,
DeployLambda,
WatchLambda
]))
],
)
}),
)
}
fn watch() -> impl Bundle {
(
Name::new("Watch"),
InsertOn::<GetOutcome, _>::new(FsWatcher::default_cargo()),
RunOnDirEvent,
InfallibleSequence,
OnSpawn::observe(|ev: On<DirEvent>| {
println!("Dir event: {}", ev.event());
}),
children![
(
Name::new("Run command"),
ContinueRun,
OnSpawn::observe(
|ev: On<GetOutcome>,
mut cmd_runner: CommandRunner|
-> Result {
let args = env_ext::args();
let args = &args[1..].join(" ");
let config = CommandConfig::parse_shell(args);
cmd_runner.run(ev, config)?;
Ok(())
}
)
),
(
Name::new("Await file change"),
),
],
)
}
#[derive(
Debug,
Clone,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Deref,
Reflect,
Component,
)]
pub struct StageParams {
#[deref]
#[reflect(
default="stage",
@ParamOptions::desc("Deployment stage: dev(default), prod, <custom>"))]
stage: String,
}
fn stage() -> String { "dev".into() }
impl Default for StageParams {
fn default() -> Self { Self { stage: stage() } }
}
fn apply_deploy_config() -> impl Bundle {
(
Name::new("Apply Deploy Config"),
OnSpawn::observe(
|ev: On<GetOutcome>,
mut pkg_config: ResMut<PackageConfig>,
mut params: RouteParamQuery<StageParams>,
mut cmd: AncestorQuery<&'static mut CargoBuildCmd>,
mut commands: Commands|
-> Result {
pkg_config.service_access = ServiceAccess::Remote;
pkg_config.stage = params.get(ev.target())?.stage;
cmd.get_mut(ev.target())?.release = true;
commands.entity(ev.target()).trigger_target(Outcome::Pass);
Ok(())
},
),
)
}
fn beet_site_cargo_build_cmd() -> CargoBuildCmd {
CargoBuildCmd::default().package("beet_site")
}