use std::future::IntoFuture;
use futures::{future::LocalBoxFuture, FutureExt};
use interruptible::Interruptibility;
use own::{OwnedOrMutRef, OwnedOrRef};
use peace_params::ParamsValue;
use peace_resource_rt::{
internal::{ProfileParamsFile, WorkspaceParamsFile},
paths::{ProfileDir, ProfileHistoryDir},
};
use peace_rt_model::{
params::{ProfileParamsOpt, WorkspaceParamsOpt},
Workspace, WorkspaceInitializer,
};
use type_reg::untagged::TypeReg;
use typed_builder::TypedBuilder;
use crate::{CmdCtxBuilderSupport, CmdCtxSpnf, CmdCtxSpnfFields, CmdCtxTypes, ProfileSelection};
#[derive(Debug, TypedBuilder)]
#[builder(build_method(vis="", name=build_partial))]
pub struct CmdCtxSpnfParams<'ctx, CmdCtxTypesT>
where
CmdCtxTypesT: CmdCtxTypes,
{
#[builder(setter(prefix = "with_"))]
pub output: OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,
#[builder(setter(prefix = "with_"), default = Interruptibility::NonInterruptible)]
pub interruptibility: Interruptibility<'static>,
#[builder(setter(prefix = "with_"))]
pub workspace: OwnedOrRef<'ctx, Workspace>,
#[builder(setter(prefix = "with_"))]
pub profile_selection: ProfileSelection<'ctx, CmdCtxTypesT::WorkspaceParamsKey>,
#[builder(
setter(prefix = "with_"),
via_mutators(init = WorkspaceParamsOpt::default()),
mutators(
/// Sets the value at the given workspace params key.
///
/// # Parameters
///
/// * `key`: The key to store the given value against.
/// * `value`: The value to store at the given key. This is an
/// `Option` so that you may remove a value if desired.
///
/// # Type Parameters
///
/// * `V`: The serializable type stored at the given key.
pub fn with_workspace_param<V>(
&mut self,
key: CmdCtxTypesT::WorkspaceParamsKey,
value: Option<V>,
)
where
V: ParamsValue,
{
let _ = self.workspace_params.insert(key, value);
}
)
)]
#[builder(setter(prefix = "with_"))]
pub workspace_params: WorkspaceParamsOpt<<CmdCtxTypesT as CmdCtxTypes>::WorkspaceParamsKey>,
#[builder(
setter(prefix = "with_"),
via_mutators(init = ProfileParamsOpt::default()),
mutators(
/// Sets the value at the given profile params key.
///
/// # Parameters
///
/// * `key`: The key to store the given value against.
/// * `value`: The value to store at the given key. This is an
/// `Option` so that you may remove a value if desired.
///
/// # Type Parameters
///
/// * `V`: The serializable type stored at the given key.
pub fn with_profile_param<V>(
&mut self,
key: CmdCtxTypesT::ProfileParamsKey,
value: Option<V>,
)
where
V: ParamsValue,
{
let _ = self.profile_params.insert(key, value);
}
)
)]
pub profile_params: ProfileParamsOpt<<CmdCtxTypesT as CmdCtxTypes>::ProfileParamsKey>,
}
#[allow(non_camel_case_types)]
impl<
'ctx,
CmdCtxTypesT,
__interruptibility: ::typed_builder::Optional<Interruptibility<'static>>,
>
CmdCtxSpnfParamsBuilder<
'ctx,
CmdCtxTypesT,
(
(OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,),
__interruptibility,
(OwnedOrRef<'ctx, Workspace>,),
(ProfileSelection<'ctx, CmdCtxTypesT::WorkspaceParamsKey>,),
(WorkspaceParamsOpt<CmdCtxTypesT::WorkspaceParamsKey>,),
(ProfileParamsOpt<CmdCtxTypesT::ProfileParamsKey>,),
),
>
where
CmdCtxTypesT: CmdCtxTypes,
{
pub async fn build(self) -> Result<CmdCtxSpnf<'ctx, CmdCtxTypesT>, CmdCtxTypesT::AppError> {
let CmdCtxSpnfParams {
output,
interruptibility,
workspace,
profile_selection,
workspace_params: workspace_params_provided,
profile_params: profile_params_provided,
} = self.build_partial();
let mut workspace_params_type_reg = TypeReg::new();
CmdCtxTypesT::workspace_params_register(&mut workspace_params_type_reg);
let mut profile_params_type_reg = TypeReg::new();
CmdCtxTypesT::profile_params_register(&mut profile_params_type_reg);
let workspace_dirs = workspace.dirs();
let storage = workspace.storage();
let workspace_params_file = WorkspaceParamsFile::from(workspace_dirs.peace_app_dir());
let workspace_params = CmdCtxBuilderSupport::workspace_params_merge(
storage,
&workspace_params_type_reg,
workspace_params_provided,
&workspace_params_file,
)
.await?;
let profile = CmdCtxBuilderSupport::profile_from_profile_selection(
profile_selection,
&workspace_params,
storage,
&workspace_params_file,
)
.await?;
let profile_ref = &profile;
let profile_dir = ProfileDir::from((workspace_dirs.peace_app_dir(), profile_ref));
let profile_history_dir = ProfileHistoryDir::from(&profile_dir);
let dirs_to_create = [
AsRef::<std::path::Path>::as_ref(workspace_dirs.workspace_dir()),
AsRef::<std::path::Path>::as_ref(workspace_dirs.peace_dir()),
AsRef::<std::path::Path>::as_ref(workspace_dirs.peace_app_dir()),
AsRef::<std::path::Path>::as_ref(&profile_dir),
AsRef::<std::path::Path>::as_ref(&profile_history_dir),
];
let storage = workspace.storage();
let profile_params_file = ProfileParamsFile::from(&profile_dir);
let profile_params = CmdCtxBuilderSupport::profile_params_merge(
storage,
&profile_params_type_reg,
profile_params_provided,
&profile_params_file,
)
.await?;
#[cfg(target_arch = "wasm32")]
{
WorkspaceInitializer::dirs_create(storage, dirs_to_create).await?;
}
#[cfg(not(target_arch = "wasm32"))]
{
WorkspaceInitializer::dirs_create(dirs_to_create).await?;
let workspace_dir = workspace_dirs.workspace_dir();
std::env::set_current_dir(workspace_dir).map_err(
#[cfg_attr(coverage_nightly, coverage(off))]
|error| {
peace_rt_model::Error::Native(peace_rt_model::NativeError::CurrentDirSet {
workspace_dir: workspace_dir.clone(),
error,
})
},
)?;
}
let interruptibility_state = interruptibility.into();
CmdCtxBuilderSupport::workspace_params_serialize(
&workspace_params,
storage,
&workspace_params_file,
)
.await?;
CmdCtxBuilderSupport::profile_params_serialize(
&profile_params,
storage,
&profile_params_file,
)
.await?;
let mut resources = peace_resource_rt::Resources::new();
CmdCtxBuilderSupport::workspace_params_insert(workspace_params.clone(), &mut resources);
resources.insert(workspace_params_file);
CmdCtxBuilderSupport::profile_params_insert(profile_params.clone(), &mut resources);
resources.insert(profile_params_file);
{
let (app_name, workspace_dirs, storage) = (*workspace).clone().into_inner();
let (workspace_dir, peace_dir, peace_app_dir) = workspace_dirs.into_inner();
resources.insert(app_name);
resources.insert(storage);
resources.insert(workspace_dir);
resources.insert(peace_dir);
resources.insert(peace_app_dir);
resources.insert(profile_dir.clone());
resources.insert(profile_history_dir.clone());
resources.insert(profile.clone());
}
let cmd_ctx_spnf = CmdCtxSpnf {
output,
fields: CmdCtxSpnfFields {
interruptibility_state,
workspace,
profile,
profile_dir,
profile_history_dir,
workspace_params_type_reg,
workspace_params,
profile_params_type_reg,
profile_params,
},
};
Ok(cmd_ctx_spnf)
}
}
#[allow(non_camel_case_types)]
impl<
'ctx,
CmdCtxTypesT,
__interruptibility: ::typed_builder::Optional<Interruptibility<'static>> + 'ctx,
> IntoFuture
for CmdCtxSpnfParamsBuilder<
'ctx,
CmdCtxTypesT,
(
(OwnedOrMutRef<'ctx, CmdCtxTypesT::Output>,),
__interruptibility,
(OwnedOrRef<'ctx, Workspace>,),
(ProfileSelection<'ctx, CmdCtxTypesT::WorkspaceParamsKey>,),
(WorkspaceParamsOpt<CmdCtxTypesT::WorkspaceParamsKey>,),
(ProfileParamsOpt<CmdCtxTypesT::ProfileParamsKey>,),
),
>
where
CmdCtxTypesT: CmdCtxTypes,
{
type IntoFuture =
LocalBoxFuture<'ctx, Result<CmdCtxSpnf<'ctx, CmdCtxTypesT>, CmdCtxTypesT::AppError>>;
type Output = <Self::IntoFuture as std::future::Future>::Output;
fn into_future(self) -> Self::IntoFuture {
self.build().boxed_local()
}
}