v0.5.3-pre.002

This commit is contained in:
2026-08-11 22:22:40 +02:00
parent 01d78b5845
commit 8448ad1079
134 changed files with 4518 additions and 3595 deletions

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/app_state.rs
// version: 17
// version: 20
//! Shared Tauri application state and startup initialization.
@@ -17,6 +17,7 @@ pub(crate) struct AppState {
active_profile: ks_config::ProfileConfig,
logging_guard: std::sync::Mutex<ks_logging::LoggingGuard>,
http_pool: ks_onchain_transport::HttpEndpointPool,
store: tokio::sync::OnceCell<ks_store::Store>,
ws_pool:
std::sync::Mutex<std::option::Option<std::sync::Arc<ks_onchain_transport::WsEndpointPool>>>,
demo_ws_session:
@@ -106,6 +107,7 @@ impl crate::AppState {
active_profile,
logging_guard: std::sync::Mutex::new(logging_guard),
http_pool,
store: tokio::sync::OnceCell::new(),
ws_pool: std::sync::Mutex::new(std::option::Option::None),
demo_ws_session: tokio::sync::Mutex::new(std::option::Option::None),
demo_backfill_running: std::sync::atomic::AtomicBool::new(false),
@@ -174,6 +176,25 @@ impl crate::AppState {
return &self.active_profile;
}
/// Returns the persistent backend-agnostic store opened from the active profile.
pub(crate) async fn store(&self) -> ks_core::Result<&ks_store::Store> {
if let std::option::Option::Some(store) = self.store.get() {
return std::result::Result::Ok(store);
}
let options = match ks_store::StoreOpenOptions::new(
self.active_profile.database.enabled,
self.active_profile.database.backend.clone(),
self.active_profile.database.backend_options.clone(),
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return self
.store
.get_or_try_init(|| return async move { return ks_store::Store::open(options).await })
.await;
}
/// Returns the session-only execution-wallet alias override for one profile.
pub(crate) fn demo_execution_wallet_alias_override(
&self,

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_backfill.rs
// version: 16
// version: 17
//! Tauri commands and UI payloads for bounded HTTP transaction backfills.
@@ -288,23 +288,10 @@ pub(crate) async fn demo_backfill_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let profile = state.active_profile();
let store_options = match ks_store::PostgresStoreOptions::new(
profile.database.postgres.url.clone(),
profile.database.postgres.max_connections,
profile.database.postgres.connect_timeout_ms,
false,
) {
let store = match crate::shared_store(state.inner()).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store = match ks_store::PostgresStore::connect(store_options).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let observer = crate::DemoBackfillObserver {
app_handle,
cancel_requested: state.demo_backfill_cancel_requested(),

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_config.rs
// version: 6
// version: 8
//! Configuration demo payloads with explicit public and bounded diagnostic projections.
@@ -164,7 +164,7 @@ pub(crate) struct DemoConfigEndpointDiagnosticPayload {
pub(crate) role_count: u32,
}
/// Store diagnostic projection without DSN or SQLite path content.
/// Backend-agnostic store diagnostic projection without backend option values.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
@@ -173,23 +173,16 @@ pub(crate) struct DemoConfigEndpointDiagnosticPayload {
pub(crate) struct DemoConfigStoreDiagnosticPayload {
/// Whether persistence is enabled.
pub(crate) enabled: bool,
/// Selected store backend.
/// Selected store backend code.
pub(crate) backend: std::string::String,
/// Whether a PostgreSQL URL is configured.
pub(crate) postgres_url_state: std::string::String,
/// PostgreSQL connection pool ceiling.
pub(crate) postgres_max_connections: u32,
/// PostgreSQL connection timeout in milliseconds.
#[ts(type = "number")]
pub(crate) postgres_connect_timeout_ms: u64,
/// Whether PostgreSQL schema initialization is enabled.
pub(crate) postgres_auto_initialize_schema: bool,
/// Whether a SQLite path is configured.
pub(crate) sqlite_path_state: std::string::String,
/// SQLite connection pool ceiling.
pub(crate) sqlite_max_connections: u32,
/// Whether SQLite schema initialization is enabled.
pub(crate) sqlite_auto_initialize_schema: bool,
/// Whether backend-specific configuration validated successfully.
pub(crate) configuration_status: std::string::String,
/// Whether a backend connection or location value is configured.
pub(crate) connection_state: std::string::String,
/// Whether automatic store initialization is enabled.
pub(crate) auto_initialize_schema: bool,
/// Number of opaque backend options supplied after composition.
pub(crate) backend_option_count: u32,
}
/// Wallet diagnostic projection without paths or secret key material.
@@ -375,17 +368,7 @@ fn diagnostic_config_payload(state: &crate::AppState) -> DemoConfigDiagnosticPay
source_diagnostic("execution", state.execution_config_path()),
],
endpoints,
store: DemoConfigStoreDiagnosticPayload {
enabled: profile.database.enabled,
backend: profile.database.backend.clone(),
postgres_url_state: configured_state(profile.database.postgres.url.as_str()),
postgres_max_connections: profile.database.postgres.max_connections,
postgres_connect_timeout_ms: profile.database.postgres.connect_timeout_ms,
postgres_auto_initialize_schema: profile.database.postgres.auto_initialize_schema,
sqlite_path_state: configured_state(profile.database.sqlite.path.as_str()),
sqlite_max_connections: profile.database.sqlite.max_connections,
sqlite_auto_initialize_schema: profile.database.sqlite.auto_initialize_schema,
},
store: store_diagnostic(profile),
wallet: DemoConfigWalletDiagnosticPayload {
wallet_directory_state: configured_state(profile.wallet.wallet_dir.as_str()),
cluster: profile.wallet.cluster.clone(),
@@ -398,6 +381,55 @@ fn diagnostic_config_payload(state: &crate::AppState) -> DemoConfigDiagnosticPay
};
}
fn store_diagnostic(profile: &ks_config::ProfileConfig) -> DemoConfigStoreDiagnosticPayload {
let backend_option_count = match profile.database.backend_options.as_object() {
std::option::Option::Some(value) => bounded_len(value.len()),
std::option::Option::None => 0,
};
let options = match ks_store::StoreOpenOptions::new(
profile.database.enabled,
profile.database.backend.clone(),
profile.database.backend_options.clone(),
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => {
return DemoConfigStoreDiagnosticPayload {
enabled: profile.database.enabled,
backend: profile.database.backend.clone(),
configuration_status: "invalid".to_string(),
connection_state: "unknown".to_string(),
auto_initialize_schema: false,
backend_option_count,
};
},
};
let summary = match options.configuration_summary() {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => {
return DemoConfigStoreDiagnosticPayload {
enabled: profile.database.enabled,
backend: profile.database.backend.clone(),
configuration_status: "invalid".to_string(),
connection_state: "unknown".to_string(),
auto_initialize_schema: false,
backend_option_count,
};
},
};
return DemoConfigStoreDiagnosticPayload {
enabled: summary.enabled,
backend: summary.backend_code,
configuration_status: "ready".to_string(),
connection_state: if summary.connection_configured {
"configured".to_string()
} else {
"missing".to_string()
},
auto_initialize_schema: summary.auto_initialize_schema,
backend_option_count: summary.backend_option_count,
};
}
fn source_diagnostic(category: &str, path: &str) -> DemoConfigSourceDiagnosticPayload {
return DemoConfigSourceDiagnosticPayload {
category: category.to_string(),
@@ -503,9 +535,19 @@ mod tests {
#[test]
fn public_and_diagnostic_projections_never_serialize_secret_canaries() {
let mut profile = active_fixture_profile();
profile.database.postgres.url =
"postgres://operator:POSTGRES-SECRET-CANARY@localhost/solana".to_string();
profile.database.sqlite.path = "/private/SQLITE-PATH-CANARY.sqlite".to_string();
if let std::option::Option::Some(options) = profile.database.backend_options.as_object_mut()
{
options.insert(
"url".to_string(),
serde_json::Value::String(
"postgres://operator:POSTGRES-SECRET-CANARY@localhost/solana".to_string(),
),
);
options.insert(
"private_path".to_string(),
serde_json::Value::String("/private/STORE-PATH-CANARY".to_string()),
);
}
profile.wallet.wallet_dir = "/private/WALLET-PATH-CANARY".to_string();
if let std::option::Option::Some(endpoint) = profile.solana.http_endpoints.first_mut() {
endpoint.url = "https://provider.invalid/?api-key=HELIUS-SECRET-CANARY".to_string();
@@ -536,17 +578,7 @@ mod tests {
};
})
.collect::<std::vec::Vec<super::DemoConfigEndpointDiagnosticPayload>>(),
store: super::DemoConfigStoreDiagnosticPayload {
enabled: profile.database.enabled,
backend: profile.database.backend.clone(),
postgres_url_state: super::configured_state(profile.database.postgres.url.as_str()),
postgres_max_connections: profile.database.postgres.max_connections,
postgres_connect_timeout_ms: profile.database.postgres.connect_timeout_ms,
postgres_auto_initialize_schema: profile.database.postgres.auto_initialize_schema,
sqlite_path_state: super::configured_state(profile.database.sqlite.path.as_str()),
sqlite_max_connections: profile.database.sqlite.max_connections,
sqlite_auto_initialize_schema: profile.database.sqlite.auto_initialize_schema,
},
store: super::store_diagnostic(&profile),
wallet: super::DemoConfigWalletDiagnosticPayload {
wallet_directory_state: super::configured_state(profile.wallet.wallet_dir.as_str()),
cluster: profile.wallet.cluster.clone(),
@@ -563,7 +595,7 @@ mod tests {
};
for secret in [
"POSTGRES-SECRET-CANARY",
"SQLITE-PATH-CANARY",
"STORE-PATH-CANARY",
"WALLET-PATH-CANARY",
"HELIUS-SECRET-CANARY",
"WS-SECRET-CANARY",

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_core_extraction.rs
// version: 14
// version: 17
//! Tauri commands and UI payloads for canonical transaction to core extraction.
@@ -221,7 +221,7 @@ pub(crate) async fn demo_core_extraction_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store_result = crate::connect_postgres_store(state.active_profile()).await;
let store_result = crate::shared_store(state).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_decode_replay.rs
// version: 40
// version: 44
//! Tauri commands and UI payloads for contextual instruction decode replay.
@@ -255,8 +255,8 @@ pub(crate) struct DemoDecodeCoverageSummaryPayload {
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_decode_replay/DemoDecodeDiagnosticsPayload.ts"
)]
pub(crate) struct DemoDecodeDiagnosticsPayload {
/// Decode, materialization and ledger table diagnostics.
pub(crate) tables: std::vec::Vec<crate::DemoSqlTableSnapshot>,
/// Decode, materialization and ledger resource diagnostics.
pub(crate) resources: std::vec::Vec<crate::DemoStoreResourceSnapshot>,
/// Aggregated declared and observed coverage.
pub(crate) coverage: std::vec::Vec<crate::DemoDecodeCoverageSummaryPayload>,
}
@@ -495,7 +495,7 @@ pub(crate) async fn demo_decode_replay_execute(
materialize_after_decode = pipeline_request.materialize_after_decode,
"start contextual decode replay pipeline"
);
let store_result = crate::connect_postgres_store(state.active_profile()).await;
let store_result = crate::shared_store(state.inner()).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
@@ -563,24 +563,24 @@ pub(crate) async fn demo_decode_replay_diagnostics(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::DemoDecodeDiagnosticsPayload, std::string::String> {
tracing::debug!(target: crate::TRACING_TARGET, action = "load_diagnostics", coverage_limit = 500_u32, "load contextual decode replay diagnostics");
let store_result = crate::connect_postgres_store(state.active_profile()).await;
let store_result = crate::shared_store(state.inner()).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let table_result = store.known_table_diagnostics().await;
let all_tables = match table_result {
let resource_result = store.known_resource_diagnostics().await;
let all_resources = match resource_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let selected_tables: std::vec::Vec<crate::DemoSqlTableSnapshot> = all_tables
let selected_resources: std::vec::Vec<crate::DemoStoreResourceSnapshot> = all_resources
.iter()
.filter(|table| {
return table.table_name.starts_with("kb_sol_decode_")
|| table.table_name.starts_with("kb_sol_mat_")
|| table.table_name == "kb_sol_ops_processing_ledger";
.filter(|resource| {
return resource.model_code == "processing"
|| resource.model_code == "decode"
|| resource.model_code == "materialization";
})
.map(crate::table_snapshot_from_pg)
.map(crate::store_resource_snapshot)
.collect();
let coverage_result = ks_store::DecodePipelineStore::list_decode_coverage_summary(
&store,
@@ -593,9 +593,9 @@ pub(crate) async fn demo_decode_replay_diagnostics(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
tracing::debug!(target: crate::TRACING_TARGET, action = "load_diagnostics", table_count = selected_tables.len(), coverage_count = coverage.len(), "contextual decode replay diagnostics loaded");
tracing::debug!(target: crate::TRACING_TARGET, action = "load_diagnostics", resource_count = selected_resources.len(), coverage_count = coverage.len(), "contextual decode replay diagnostics loaded");
return std::result::Result::Ok(crate::DemoDecodeDiagnosticsPayload {
tables: selected_tables,
resources: selected_resources,
coverage: coverage.into_iter().map(coverage_payload).collect(),
});
}
@@ -616,7 +616,7 @@ pub(crate) async fn demo_decode_replay_annotations(
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
tracing::debug!(target: crate::TRACING_TARGET, action = "load_transaction_annotations", signature_contains = ?filter.signature_contains, limit = filter.limit, "load bounded committed transaction annotation journal");
let store_result = crate::connect_postgres_store(state.active_profile()).await;
let store_result = crate::shared_store(state.inner()).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_devnet_common.rs
// version: 6
// version: 7
//! Shared Devnet demo UI contracts.
@@ -7,7 +7,7 @@ use ts_rs::TS; // rust-rules: derive-import
const DEMO_WALLET_PASSWORD_ENV: &str = "KB_SECRET_DEMO_WALLET_PASSWORD";
/// Readiness report for one Devnet profile PostgreSQL store.
/// Backend-agnostic readiness report for one Devnet profile store.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
@@ -17,16 +17,18 @@ const DEMO_WALLET_PASSWORD_ENV: &str = "KB_SECRET_DEMO_WALLET_PASSWORD";
pub(crate) struct DemoExecutionDevnetStoreReadinessPayload {
/// Selected Devnet profile.
pub(crate) profile_name: std::string::String,
/// Selected backend code.
pub(crate) backend: std::string::String,
/// Whether schema creation was allowed by configuration.
pub(crate) auto_initialize_schema: bool,
/// Number of known tables already present before preparation.
pub(crate) existing_tables_before: u32,
/// Number of known tables created during preparation.
pub(crate) created_tables: u32,
/// Number of known tables present after preparation.
pub(crate) existing_tables_after: u32,
/// Total number of known tables expected by the current store.
pub(crate) expected_tables: u32,
/// Number of logical resources already present before preparation.
pub(crate) available_resources_before: u32,
/// Number of logical resources created during preparation.
pub(crate) created_resources: u32,
/// Number of logical resources present after preparation.
pub(crate) available_resources_after: u32,
/// Total number of logical resources expected by the current store contract.
pub(crate) expected_resources: u32,
}
/// Converts the reusable scenario readiness report to the desktop TS-RS payload.
@@ -35,11 +37,12 @@ pub(crate) fn devnet_store_readiness_payload(
) -> DemoExecutionDevnetStoreReadinessPayload {
return DemoExecutionDevnetStoreReadinessPayload {
profile_name: readiness.profile_name,
backend: readiness.backend,
auto_initialize_schema: readiness.auto_initialize_schema,
existing_tables_before: bounded_u32(readiness.existing_tables_before),
created_tables: bounded_u32(readiness.created_tables),
existing_tables_after: bounded_u32(readiness.existing_tables_after),
expected_tables: bounded_u32(readiness.expected_tables),
available_resources_before: bounded_u32(readiness.available_resources_before),
created_resources: bounded_u32(readiness.created_resources),
available_resources_after: bounded_u32(readiness.available_resources_after),
expected_resources: bounded_u32(readiness.expected_resources),
};
}

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_execution_metadata_metaplex_token_metadata.rs
// version: 11
// version: 13
//! Desktop adapters for generic and qualified Metaplex Token Metadata execution workflows.
@@ -190,13 +190,10 @@ pub(crate) async fn demo_execution_metadata_metaplex_token_metadata_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
let store = match crate::open_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let mut execution_request = match ks_pipeline_demo_scenarios::DevnetMetaplexTokenMetadataExecutionRequest::from_operation_json(
request.intent_id,
request.operation_json.as_str(),
@@ -1044,13 +1041,10 @@ pub(crate) async fn demo_execution_metadata_metaplex_execute_campaign(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
let store = match crate::open_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let workspace_root = crate::workspace_root_dir();
let configured_wallet_dir =
std::path::PathBuf::from(profile.wallet.temporary_wallet_dir.as_str());

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_execution_metadata_token_2022.rs
// version: 5
// version: 7
//! Thin desktop adapter for the complete Token-2022 Token Metadata Devnet campaign.
@@ -88,13 +88,10 @@ pub(crate) async fn demo_execution_metadata_token_2022_execute_campaign(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
let store = match crate::open_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let workspace_root = crate::workspace_root_dir();
let configured_wallet_dir =
std::path::PathBuf::from(profile.wallet.temporary_wallet_dir.as_str());

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_execution_solana_core.rs
// version: 20
// version: 23
//! Tauri adapter for bounded Solana Core execution on Devnet.
@@ -394,7 +394,7 @@ pub(crate) fn confirmation_status_code(
};
}
/// Verifies or initializes the PostgreSQL schema selected by one Devnet profile.
/// Verifies or initializes the configured store selected by one Devnet profile.
pub(crate) async fn demo_execution_devnet_prepare_profile(
state: tauri::State<'_, crate::AppState>,
profile_name: std::string::String,
@@ -473,14 +473,10 @@ pub(crate) async fn demo_execution_solana_core_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
let store = match crate::open_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let initialize_result = store.initialize_store_schema().await;
if let std::result::Result::Err(error) = initialize_result {
return std::result::Result::Err(error.to_string());
}
let mut pipeline_request = ks_pipeline_demo_scenarios::DevnetSystemTransferRequest::new(
format!("demo-execution-{}", chrono::Utc::now().timestamp_micros()),
ks_lib::MdPubkey(request.recipient.trim().to_string()),
@@ -561,13 +557,10 @@ pub(crate) async fn demo_execution_spl_memo_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
let store = match crate::open_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let mut pipeline_request = ks_pipeline_demo_scenarios::DevnetMemoExecutionRequest::new(
format!("demo-memo-execution-{}", chrono::Utc::now().timestamp_micros()),
request.message,

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_spl_ata.rs
// version: 16
// version: 18
//! Thin Tauri adapter for ATA execution, derivation and lifecycle journal reads.
@@ -260,13 +260,10 @@ pub(crate) async fn demo_execution_spl_ata_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
let store = match crate::open_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let decoders: std::vec::Vec<std::sync::Arc<dyn ks_lib::DcApiInstructionDecoder>> = std::vec![
std::sync::Arc::new(ks_lib::DcSplAssociatedTokenAccountDecoder),
std::sync::Arc::new(ks_lib::DcSplTokenDecoder),
@@ -315,7 +312,7 @@ pub(crate) async fn demo_spl_ata_journal(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store = match crate::connect_postgres_store(&profile).await {
let store = match crate::open_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_spl_token.rs
// version: 13
// version: 16
//! Thin Tauri adapter for classic SPL Token execution and materialized journals.
@@ -99,7 +99,7 @@ pub(crate) struct DemoExecutionSplTokenSummaryPayload {
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_token/DemoSplTokenJournalRequest.ts"
)]
pub(crate) struct DemoSplTokenJournalRequest {
/// Devnet profile whose PostgreSQL store is queried.
/// Devnet profile whose configured store is queried.
pub(crate) profile_name: std::string::String,
/// Optional partial signature handled by the bounded store query.
pub(crate) signature_contains: std::option::Option<std::string::String>,
@@ -183,13 +183,10 @@ pub(crate) async fn demo_execution_spl_token_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
let store = match crate::open_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let amount_raw = request.amount_raw.trim().to_string();
let operation = ks_lib::ExSplClassicTokenOperation::Instruction {
value: ks_lib::ExSplClassicTokenSingleOperation::TransferChecked {
@@ -259,13 +256,10 @@ pub(crate) async fn demo_spl_token_journal(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let store = match crate::connect_postgres_store(&profile).await {
let store = match crate::open_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let needs_payload_filter =
validated.mint.is_some() || validated.account.is_some() || validated.operation.is_some();
let query_limit = if needs_payload_filter {

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_spl_token_2022.rs
// version: 18
// version: 20
//! Thin Tauri adapter for independent public Token-2022 Devnet validation scenarios.
@@ -159,13 +159,10 @@ pub(crate) async fn demo_execution_spl_token_2022_execute(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store = match crate::connect_postgres_store(&profile).await {
let store = match crate::open_store(&profile).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
if let std::result::Result::Err(error) = store.initialize_store_schema().await {
return std::result::Result::Err(error.to_string());
}
let operation = match operation_from_request(&request) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),

View File

@@ -1,312 +0,0 @@
// file: kb-app-demo-desktop/src/demo_sql_common.rs
// version: 13
//! Shared SQL demo helpers and serializable payloads.
use ts_rs::TS; // rust-rules: derive-import
/// UI-safe table diagnostics shown by SQL demo windows.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_sql/DemoSqlTableSnapshot.ts"
)]
pub(crate) struct DemoSqlTableSnapshot {
/// Table name.
pub(crate) table_name: std::string::String,
/// Logical Solana domain encoded in the table name.
pub(crate) domain: std::string::String,
/// Human-readable table role.
pub(crate) role: std::string::String,
/// Whether the table currently exists.
pub(crate) exists: bool,
/// Row count when the table exists.
#[ts(type = "number | null")]
pub(crate) row_count: std::option::Option<i64>,
/// Minimum slot when available.
#[ts(type = "number | null")]
pub(crate) min_slot: std::option::Option<i64>,
/// Maximum slot when available.
#[ts(type = "number | null")]
pub(crate) max_slot: std::option::Option<i64>,
/// Latest insertion timestamp rendered by PostgreSQL when available.
pub(crate) latest_created_at: std::option::Option<std::string::String>,
}
/// Builds PostgreSQL options from the active profile without coupling ks-store to ks-config.
pub(crate) fn postgres_store_options_from_profile(
profile: &ks_config::ProfileConfig,
auto_initialize_schema: bool,
) -> ks_core::Result<ks_store::PostgresStoreOptions> {
return ks_store::PostgresStoreOptions::new(
profile.database.postgres.url.clone(),
profile.database.postgres.max_connections,
profile.database.postgres.connect_timeout_ms,
auto_initialize_schema,
);
}
/// Connects to PostgreSQL without reapplying schemas initialized at application startup.
pub(crate) async fn connect_postgres_store(
profile: &ks_config::ProfileConfig,
) -> std::result::Result<ks_store::PostgresStore, std::string::String> {
if !profile.database.enabled {
return std::result::Result::Err(std::string::String::from(
"database configuration is disabled in the active profile",
));
}
let options_result = postgres_store_options_from_profile(profile, false);
let mut options = match options_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
options.auto_initialize_schema = false;
let store_result = ks_store::PostgresStore::connect(options).await;
return match store_result {
std::result::Result::Ok(store) => std::result::Result::Ok(store),
std::result::Result::Err(error) => std::result::Result::Err(error.to_string()),
};
}
/// Converts store table diagnostics to the UI payload shape.
pub(crate) fn table_snapshot_from_pg(
value: &ks_store::PostgresTableDiagnostics,
) -> crate::DemoSqlTableSnapshot {
let row_count = match &value.statistics {
std::option::Option::Some(statistics) => std::option::Option::Some(statistics.row_count),
std::option::Option::None => std::option::Option::None,
};
let min_slot = match &value.statistics {
std::option::Option::Some(statistics) => statistics.min_slot,
std::option::Option::None => std::option::Option::None,
};
let max_slot = match &value.statistics {
std::option::Option::Some(statistics) => statistics.max_slot,
std::option::Option::None => std::option::Option::None,
};
let latest_created_at = match &value.statistics {
std::option::Option::Some(statistics) => statistics.latest_created_at.clone(),
std::option::Option::None => std::option::Option::None,
};
return crate::DemoSqlTableSnapshot {
table_name: value.table_name.clone(),
domain: value.domain.clone(),
role: value.role.clone(),
exists: value.exists,
row_count,
min_slot,
max_slot,
latest_created_at,
};
}
/// Converts many table diagnostics to UI payloads.
pub(crate) fn table_snapshots_from_pg(
values: &[ks_store::PostgresTableDiagnostics],
) -> std::vec::Vec<crate::DemoSqlTableSnapshot> {
let mut output = std::vec::Vec::new();
for value in values {
output.push(crate::table_snapshot_from_pg(value));
}
return output;
}
/// Initializes PostgreSQL raw, core, decode and materialization schemas during Tauri startup.
pub(crate) async fn initialize_postgres_schema_for_startup(
state: &crate::AppState,
splash_window: &tauri::WebviewWindow,
) {
let profile = state.active_profile();
if !profile.database.enabled {
emit_sql_startup_splash(
splash_window,
"SQL store disabled; schema initialization skipped.",
"info",
false,
);
tracing::debug!(target: crate::TRACING_TARGET, "database is disabled; skip SQL schema initialization");
return;
}
if profile.database.backend != "postgres" {
emit_sql_startup_splash(
splash_window,
"SQL backend is not PostgreSQL; schema initialization skipped.",
"info",
false,
);
tracing::debug!(target: crate::TRACING_TARGET, backend = profile.database.backend.as_str(), "database backend is not postgres; skip SQL schema initialization");
return;
}
let options_result = postgres_store_options_from_profile(
profile,
profile.database.postgres.auto_initialize_schema,
);
let mut options = match options_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
let error_message = error.to_string();
emit_sql_startup_error(splash_window, error_message.as_str());
tracing::error!(target: crate::TRACING_TARGET, error = error_message.as_str(), "cannot build PostgreSQL store options");
return;
},
};
let initialize_schema = options.auto_initialize_schema;
let masked_dsn = options.masked_dsn();
options.auto_initialize_schema = false;
emit_sql_startup_splash(
splash_window,
"Connexion PostgreSQL et vérification des tables raw/core/decode...",
"info",
false,
);
if !initialize_schema {
emit_sql_startup_splash(
splash_window,
"Auto-initialisation désactivée : vérification sans création de table.",
"info",
true,
);
}
tracing::debug!(target: crate::TRACING_TARGET, dsn = masked_dsn.as_str(), "start PostgreSQL schema initialization");
let store_result = ks_store::PostgresStore::connect(options).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
let error_message = error.to_string();
emit_sql_startup_error(splash_window, error_message.as_str());
tracing::error!(target: crate::TRACING_TARGET, error = error_message.as_str(), "PostgreSQL connection failed during startup schema initialization");
return;
},
};
let before_result = store.known_table_diagnostics().await;
let before_tables = match before_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
let error_message = error.to_string();
emit_sql_startup_error(splash_window, error_message.as_str());
tracing::error!(target: crate::TRACING_TARGET, error = error_message.as_str(), "cannot read table diagnostics before schema initialization");
return;
},
};
if initialize_schema {
let initialize_result = store.initialize_store_schema().await;
if let std::result::Result::Err(error) = initialize_result {
let error_message = error.to_string();
emit_sql_startup_error(splash_window, error_message.as_str());
tracing::error!(target: crate::TRACING_TARGET, error = error_message.as_str(), "PostgreSQL store schema initialization failed");
return;
}
}
let after_result = store.known_table_diagnostics().await;
let after_tables = match after_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
let error_message = error.to_string();
emit_sql_startup_error(splash_window, error_message.as_str());
tracing::error!(target: crate::TRACING_TARGET, error = error_message.as_str(), "cannot read table diagnostics after schema initialization");
return;
},
};
emit_sql_startup_table_report(splash_window, before_tables.as_slice(), after_tables.as_slice());
}
/// Formats debug enums for UI display.
pub(crate) fn debug_status<T: std::fmt::Debug>(value: T) -> std::string::String {
return format!("{value:?}");
}
fn emit_sql_startup_table_report(
splash_window: &tauri::WebviewWindow,
before_tables: &[ks_store::PostgresTableDiagnostics],
after_tables: &[ks_store::PostgresTableDiagnostics],
) {
let mut created_count = 0_u32;
let mut existing_count = 0_u32;
let mut missing_count = 0_u32;
for table in after_tables {
let before_exists = table_exists_in(before_tables, table.table_name.as_str());
if table.exists && before_exists == std::option::Option::Some(false) {
created_count += 1;
emit_sql_startup_splash(
splash_window,
format!("Created table {}", table.table_name).as_str(),
"success",
true,
);
tracing::debug!(target: crate::TRACING_TARGET, table = table.table_name.as_str(), "PostgreSQL table created");
} else if table.exists {
existing_count += 1;
emit_sql_startup_splash(
splash_window,
format!("Table {} already exists", table.table_name).as_str(),
"info",
true,
);
tracing::debug!(target: crate::TRACING_TARGET, table = table.table_name.as_str(), "PostgreSQL table already exists");
} else {
missing_count += 1;
emit_sql_startup_splash(
splash_window,
format!("Table {} is missing after initialization", table.table_name).as_str(),
"warning",
true,
);
tracing::error!(target: crate::TRACING_TARGET, table = table.table_name.as_str(), "PostgreSQL table missing after initialization");
}
}
emit_sql_startup_splash(
splash_window,
format!(
"PostgreSQL schema ready: {created_count} created, {existing_count} already present, {missing_count} missing."
)
.as_str(),
schema_report_status(missing_count),
false,
);
tracing::debug!(target: crate::TRACING_TARGET, created = created_count, existing = existing_count, missing = missing_count, "PostgreSQL schema initialization completed");
}
fn table_exists_in(
tables: &[ks_store::PostgresTableDiagnostics],
table_name: &str,
) -> std::option::Option<bool> {
for table in tables {
if table.table_name.as_str() == table_name {
return std::option::Option::Some(table.exists);
}
}
return std::option::Option::None;
}
fn schema_report_status(missing_count: u32) -> &'static str {
if missing_count == 0 {
return "success";
}
return "warning";
}
fn emit_sql_startup_error(splash_window: &tauri::WebviewWindow, message: &str) {
emit_sql_startup_splash(
splash_window,
format!("PostgreSQL schema initialization error: {message}").as_str(),
"danger",
false,
);
}
fn emit_sql_startup_splash(
splash_window: &tauri::WebviewWindow,
message: &str,
status: &str,
log_only: bool,
) {
let order = if log_only { "add_log" } else { "add_msg" };
crate::emit_splash_order(
splash_window,
order,
std::option::Option::Some(message),
std::option::Option::Some(status),
std::option::Option::None,
);
}

View File

@@ -1,73 +0,0 @@
// file: kb-app-demo-desktop/src/demo_sql_diag.rs
// version: 5
//! SQL diagnostic demo commands.
use ts_rs::TS; // rust-rules: derive-import
/// Complete SQL diagnostic payload shown by `demo_sql_diag`.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_sql_diag/DemoSqlDiagPayload.ts"
)]
pub(crate) struct DemoSqlDiagPayload {
/// Configuration file path.
pub(crate) config_path: std::string::String,
/// Active profile name.
pub(crate) active_profile_name: std::string::String,
/// Configured database backend.
pub(crate) backend: std::string::String,
/// Masked PostgreSQL DSN.
pub(crate) masked_dsn: std::string::String,
/// PostgreSQL current schema.
pub(crate) current_schema: std::option::Option<std::string::String>,
/// PostgreSQL health status.
pub(crate) health_status: std::string::String,
/// PostgreSQL health message.
pub(crate) health_message: std::option::Option<std::string::String>,
/// Migration status.
pub(crate) migration_status: std::string::String,
/// Migration diagnostic message.
pub(crate) migration_message: std::option::Option<std::string::String>,
/// PostgreSQL server version when available.
pub(crate) server_version: std::option::Option<std::string::String>,
/// Known raw/core table diagnostics.
pub(crate) tables: std::vec::Vec<crate::DemoSqlTableSnapshot>,
}
/// Loads read-only SQL diagnostics from the active profile.
pub(crate) async fn load_demo_sql_diag(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::DemoSqlDiagPayload, std::string::String> {
let profile = state.active_profile().clone();
let store_result = crate::connect_postgres_store(&profile).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let diagnostics_result = store.backend_diagnostics().await;
let diagnostics = match diagnostics_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let tables_result = store.known_table_diagnostics().await;
let tables = match tables_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
return std::result::Result::Ok(crate::DemoSqlDiagPayload {
config_path: state.config_path().to_string(),
active_profile_name: profile.name.clone(),
backend: profile.database.backend.clone(),
masked_dsn: store.options().masked_dsn(),
current_schema: diagnostics.descriptor.current_schema,
health_status: crate::debug_status(diagnostics.health.status),
health_message: diagnostics.health.message,
migration_status: crate::debug_status(diagnostics.migrations.status),
migration_message: diagnostics.migrations.message,
server_version: diagnostics.server_version,
tables: crate::table_snapshots_from_pg(tables.as_slice()),
});
}

View File

@@ -1,44 +0,0 @@
// file: kb-app-demo-desktop/src/demo_sql_pg_core.rs
// version: 6
//! PostgreSQL core store demo commands.
use ts_rs::TS; // rust-rules: derive-import
/// PostgreSQL core store payload shown by `demo_sql_pg_core`.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_sql_pg_core/DemoSqlPgCorePayload.ts"
)]
pub(crate) struct DemoSqlPgCorePayload {
/// Active profile name.
pub(crate) active_profile_name: std::string::String,
/// Masked PostgreSQL DSN.
pub(crate) masked_dsn: std::string::String,
/// Core table diagnostics.
pub(crate) tables: std::vec::Vec<crate::DemoSqlTableSnapshot>,
}
/// Loads read-only core table diagnostics from PostgreSQL.
pub(crate) async fn load_demo_sql_pg_core(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::DemoSqlPgCorePayload, std::string::String> {
let profile = state.active_profile().clone();
let store_result = crate::connect_postgres_store(&profile).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let tables_result = store.core_table_diagnostics().await;
let tables = match tables_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
return std::result::Result::Ok(crate::DemoSqlPgCorePayload {
active_profile_name: profile.name.clone(),
masked_dsn: store.options().masked_dsn(),
tables: crate::table_snapshots_from_pg(tables.as_slice()),
});
}

View File

@@ -1,44 +0,0 @@
// file: kb-app-demo-desktop/src/demo_sql_pg_raw.rs
// version: 7
//! PostgreSQL canonical acquisition store demo commands.
use ts_rs::TS; // rust-rules: derive-import
/// PostgreSQL canonical acquisition payload shown by `demo_sql_pg_raw`.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_sql_pg_raw/DemoSqlPgRawPayload.ts"
)]
pub(crate) struct DemoSqlPgRawPayload {
/// Active profile name.
pub(crate) active_profile_name: std::string::String,
/// Masked PostgreSQL DSN.
pub(crate) masked_dsn: std::string::String,
/// Raw table diagnostics.
pub(crate) tables: std::vec::Vec<crate::DemoSqlTableSnapshot>,
}
/// Loads read-only raw table diagnostics from PostgreSQL.
pub(crate) async fn load_demo_sql_pg_raw(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::DemoSqlPgRawPayload, std::string::String> {
let profile = state.active_profile().clone();
let store_result = crate::connect_postgres_store(&profile).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let tables_result = store.raw_table_diagnostics().await;
let tables = match tables_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
return std::result::Result::Ok(crate::DemoSqlPgRawPayload {
active_profile_name: profile.name.clone(),
masked_dsn: store.options().masked_dsn(),
tables: crate::table_snapshots_from_pg(tables.as_slice()),
});
}

View File

@@ -0,0 +1,264 @@
// file: kb-app-demo-desktop/src/demo_store_common.rs
// version: 19
//! Shared backend-agnostic store demo helpers and serializable payloads.
use ts_rs::TS; // rust-rules: derive-import
/// UI-safe diagnostics for one logical store resource.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store/DemoStoreResourceSnapshot.ts"
)]
pub(crate) struct DemoStoreResourceSnapshot {
/// Stable logical resource code independent of the active backend.
pub(crate) resource_code: std::string::String,
/// Logical store model containing the resource.
pub(crate) model_code: std::string::String,
/// Human-readable resource role.
pub(crate) role: std::string::String,
/// Whether the logical resource is currently available.
pub(crate) available: bool,
/// Record count when the resource is available.
#[ts(type = "number | null")]
pub(crate) record_count: std::option::Option<i64>,
/// Minimum slot when available.
#[ts(type = "number | null")]
pub(crate) min_slot: std::option::Option<i64>,
/// Maximum slot when available.
#[ts(type = "number | null")]
pub(crate) max_slot: std::option::Option<i64>,
/// Latest persistence timestamp when available.
pub(crate) latest_created_at: std::option::Option<std::string::String>,
}
/// Builds backend-agnostic store-open options from one resolved profile.
fn store_open_options_from_profile(
profile: &ks_config::ProfileConfig,
) -> ks_core::Result<ks_store::StoreOpenOptions> {
return ks_store::StoreOpenOptions::new(
profile.database.enabled,
profile.database.backend.clone(),
profile.database.backend_options.clone(),
);
}
/// Opens a backend-agnostic store from one resolved profile.
///
/// Prefer [`crate::AppState::store`] for desktop commands that already own application state.
pub(crate) async fn open_store(
profile: &ks_config::ProfileConfig,
) -> std::result::Result<ks_store::Store, std::string::String> {
let options = match store_open_options_from_profile(profile) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
return match ks_store::Store::open(options).await {
std::result::Result::Ok(store) => std::result::Result::Ok(store),
std::result::Result::Err(error) => std::result::Result::Err(error.to_string()),
};
}
/// Clones the persistent store held by application state.
pub(crate) async fn shared_store(
state: &crate::AppState,
) -> std::result::Result<ks_store::Store, std::string::String> {
let store_result = state.store().await;
return match store_result {
std::result::Result::Ok(store) => std::result::Result::Ok(store.clone()),
std::result::Result::Err(error) => std::result::Result::Err(error.to_string()),
};
}
/// Converts one logical store resource diagnostic to the UI payload shape.
pub(crate) fn store_resource_snapshot(
value: &ks_store::StoreResourceDiagnostics,
) -> crate::DemoStoreResourceSnapshot {
let record_count = match &value.statistics {
std::option::Option::Some(statistics) => std::option::Option::Some(statistics.record_count),
std::option::Option::None => std::option::Option::None,
};
let min_slot = match &value.statistics {
std::option::Option::Some(statistics) => statistics.min_slot,
std::option::Option::None => std::option::Option::None,
};
let max_slot = match &value.statistics {
std::option::Option::Some(statistics) => statistics.max_slot,
std::option::Option::None => std::option::Option::None,
};
let latest_created_at = match &value.statistics {
std::option::Option::Some(statistics) => statistics.latest_created_at.clone(),
std::option::Option::None => std::option::Option::None,
};
return crate::DemoStoreResourceSnapshot {
resource_code: value.resource_code.clone(),
model_code: value.model_code.clone(),
role: value.role.clone(),
available: value.available,
record_count,
min_slot,
max_slot,
latest_created_at,
};
}
/// Converts many logical store resource diagnostics to UI payloads.
pub(crate) fn store_resource_snapshots(
values: &[ks_store::StoreResourceDiagnostics],
) -> std::vec::Vec<crate::DemoStoreResourceSnapshot> {
let mut output = std::vec::Vec::with_capacity(values.len());
for value in values {
output.push(crate::store_resource_snapshot(value));
}
return output;
}
/// Opens, auto-initializes when configured, and verifies the persistent store during startup.
pub(crate) async fn initialize_store_for_startup(
state: &crate::AppState,
splash_window: &tauri::WebviewWindow,
) {
let store_result = state.store().await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
let error_message = error.to_string();
emit_store_startup_error(splash_window, error_message.as_str());
tracing::error!(target: crate::TRACING_TARGET, error = error_message.as_str(), "store startup failed");
return;
},
};
let configuration = store.configuration_summary();
if !configuration.enabled {
emit_store_startup_splash(
splash_window,
"Store disabled; initialization skipped.",
"info",
false,
);
tracing::debug!(target: crate::TRACING_TARGET, backend = configuration.backend_code.as_str(), "store disabled; startup initialization skipped");
return;
}
emit_store_startup_splash(
splash_window,
format!(
"Store backend {}: vérification des modèles de persistance...",
configuration.backend_code
)
.as_str(),
"info",
false,
);
let initialization = store.initialization_summary();
for model in &initialization.models {
emit_store_startup_splash(
splash_window,
format!(
"Modèle {}: {}/{} ressources disponibles, {} créées.",
model.model_code,
model.available_resource_count,
model.expected_resource_count,
model.created_resource_count
)
.as_str(),
model_status(&model.status),
true,
);
}
for object in &initialization.objects {
emit_store_startup_splash(
splash_window,
format!(
"Objets {}: {}/{} disponibles, {} créés.",
object.object_kind,
object.available_count,
object.expected_count,
object.created_count
)
.as_str(),
"info",
true,
);
}
emit_store_startup_splash(
splash_window,
format!(
"Store {:?}: ressources {}/{}, {} créées.",
initialization.status,
initialization.available_resource_count,
initialization.expected_resource_count,
initialization.created_resource_count
)
.as_str(),
initialization_status(&initialization.status),
false,
);
tracing::debug!(target: crate::TRACING_TARGET, backend = configuration.backend_code.as_str(), available_resources = initialization.available_resource_count, expected_resources = initialization.expected_resource_count, created_resources = initialization.created_resource_count, "store startup verification completed");
}
/// Returns the safe connection descriptor exposed by the active backend.
pub(crate) async fn store_connection_descriptor(
store: &ks_store::Store,
) -> std::result::Result<std::string::String, std::string::String> {
let runtime = match store.runtime_summary().await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let backend = match runtime.backend {
std::option::Option::Some(value) => value,
std::option::Option::None => return std::result::Result::Ok("disabled".to_string()),
};
let descriptor = match backend.descriptor.masked_connection_descriptor {
std::option::Option::Some(value) => value,
std::option::Option::None => "configured".to_string(),
};
return std::result::Result::Ok(descriptor);
}
/// Formats debug enums for UI display.
pub(crate) fn debug_status<T: std::fmt::Debug>(value: T) -> std::string::String {
return format!("{value:?}");
}
fn model_status(status: &ks_store::StoreModelVerificationStatus) -> &'static str {
return match status {
ks_store::StoreModelVerificationStatus::Ready => "success",
ks_store::StoreModelVerificationStatus::Incomplete => "warning",
};
}
fn initialization_status(status: &ks_store::StoreInitializationStatus) -> &'static str {
return match status {
ks_store::StoreInitializationStatus::Ready => "success",
ks_store::StoreInitializationStatus::Disabled => "info",
ks_store::StoreInitializationStatus::Partial => "warning",
ks_store::StoreInitializationStatus::Failed => "danger",
};
}
fn emit_store_startup_error(splash_window: &tauri::WebviewWindow, message: &str) {
emit_store_startup_splash(
splash_window,
format!("Store initialization error: {message}").as_str(),
"danger",
false,
);
}
fn emit_store_startup_splash(
splash_window: &tauri::WebviewWindow,
message: &str,
status: &str,
log_only: bool,
) {
let order = if log_only { "add_log" } else { "add_msg" };
crate::emit_splash_order(
splash_window,
order,
std::option::Option::Some(message),
std::option::Option::Some(status),
std::option::Option::None,
);
}

View File

@@ -0,0 +1,45 @@
// file: kb-app-demo-desktop/src/demo_store_core.rs
// version: 9
//! Backend-agnostic Core store demo commands retained by the store window.
use ts_rs::TS; // rust-rules: derive-import
/// Backend-agnostic Core store payload shown by the existing `demo_store_core` window.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_core/DemoStoreCorePayload.ts"
)]
pub(crate) struct DemoStoreCorePayload {
/// Active profile name.
pub(crate) active_profile_name: std::string::String,
/// Safe backend connection descriptor.
pub(crate) connection_descriptor: std::string::String,
/// Logical Core-resource diagnostics.
pub(crate) resources: std::vec::Vec<crate::DemoStoreResourceSnapshot>,
}
/// Loads read-only Core resource diagnostics from the active store.
pub(crate) async fn load_demo_store_core(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::DemoStoreCorePayload, std::string::String> {
let store = match crate::shared_store(state.inner()).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let resources = match store.core_resource_diagnostics().await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let connection_descriptor = match crate::store_connection_descriptor(&store).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return std::result::Result::Ok(crate::DemoStoreCorePayload {
active_profile_name: state.active_profile().name.clone(),
connection_descriptor,
resources: crate::store_resource_snapshots(resources.as_slice()),
});
}

View File

@@ -0,0 +1,81 @@
// file: kb-app-demo-desktop/src/demo_store_diag.rs
// version: 9
//! Backend-agnostic store diagnostic demo commands retained by the Store diagnostics window.
use ts_rs::TS; // rust-rules: derive-import
/// Complete backend-neutral store diagnostic payload shown by `demo_store_diag`.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_diag/DemoStoreDiagPayload.ts"
)]
pub(crate) struct DemoStoreDiagPayload {
/// Configuration file path.
pub(crate) config_path: std::string::String,
/// Active profile name.
pub(crate) active_profile_name: std::string::String,
/// Active backend code.
pub(crate) backend: std::string::String,
/// Safe backend connection descriptor.
pub(crate) connection_descriptor: std::string::String,
/// Backend namespace, schema, or equivalent logical location.
pub(crate) namespace: std::option::Option<std::string::String>,
/// Store health status.
pub(crate) health_status: std::string::String,
/// Store health message.
pub(crate) health_message: std::option::Option<std::string::String>,
/// Migration status.
pub(crate) migration_status: std::string::String,
/// Migration diagnostic message.
pub(crate) migration_message: std::option::Option<std::string::String>,
/// Backend version when available.
pub(crate) backend_version: std::option::Option<std::string::String>,
/// Known logical store resource diagnostics.
pub(crate) resources: std::vec::Vec<crate::DemoStoreResourceSnapshot>,
}
/// Loads read-only diagnostics from the active store.
pub(crate) async fn load_demo_store_diag(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::DemoStoreDiagPayload, std::string::String> {
let store = match crate::shared_store(state.inner()).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let runtime = match store.runtime_summary().await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let resources = match store.known_resource_diagnostics().await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let backend = match runtime.backend {
std::option::Option::Some(value) => value,
std::option::Option::None => {
return std::result::Result::Err(
"store backend diagnostics are unavailable".to_string(),
);
},
};
let connection_descriptor = match backend.descriptor.masked_connection_descriptor.clone() {
std::option::Option::Some(value) => value,
std::option::Option::None => "configured".to_string(),
};
return std::result::Result::Ok(crate::DemoStoreDiagPayload {
config_path: state.config_path().to_string(),
active_profile_name: state.active_profile().name.clone(),
backend: backend.descriptor.backend_code,
connection_descriptor,
namespace: backend.descriptor.namespace,
health_status: crate::debug_status(backend.health.status),
health_message: backend.health.message,
migration_status: crate::debug_status(backend.migrations.status),
migration_message: backend.migrations.message,
backend_version: backend.backend_version,
resources: crate::store_resource_snapshots(resources.as_slice()),
});
}

View File

@@ -0,0 +1,45 @@
// file: kb-app-demo-desktop/src/demo_store_raw.rs
// version: 10
//! Backend-agnostic level-1 raw store demo commands retained by the store window.
use ts_rs::TS; // rust-rules: derive-import
/// Backend-agnostic raw store payload shown by the existing `demo_store_raw` window.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_raw/DemoStoreRawPayload.ts"
)]
pub(crate) struct DemoStoreRawPayload {
/// Active profile name.
pub(crate) active_profile_name: std::string::String,
/// Safe backend connection descriptor.
pub(crate) connection_descriptor: std::string::String,
/// Logical raw-resource diagnostics.
pub(crate) resources: std::vec::Vec<crate::DemoStoreResourceSnapshot>,
}
/// Loads read-only level-1 raw resource diagnostics from the active store.
pub(crate) async fn load_demo_store_raw(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::DemoStoreRawPayload, std::string::String> {
let store = match crate::shared_store(state.inner()).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let resources = match store.raw_resource_diagnostics().await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let connection_descriptor = match crate::store_connection_descriptor(&store).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return std::result::Result::Ok(crate::DemoStoreRawPayload {
active_profile_name: state.active_profile().name.clone(),
connection_descriptor,
resources: crate::store_resource_snapshots(resources.as_slice()),
});
}

View File

@@ -1,7 +1,7 @@
// file: kb-app-demo-desktop/src/demo_sql_replay_candidates.rs
// version: 13
// file: kb-app-demo-desktop/src/demo_store_replay_candidates.rs
// version: 16
//! Read-only SQL replay candidate browser commands.
//! Backend-agnostic read-only replay candidate browser commands.
use ts_rs::TS; // rust-rules: derive-import
@@ -10,9 +10,9 @@ use ts_rs::TS; // rust-rules: derive-import
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_sql_replay_candidates/DemoSqlReplayKnownProgramOption.ts"
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_replay_candidates/DemoStoreReplayKnownProgramOption.ts"
)]
pub(crate) struct DemoSqlReplayKnownProgramOption {
pub(crate) struct DemoStoreReplayKnownProgramOption {
/// Stable lower snake case program code.
pub(crate) code: std::string::String,
/// Base58 Solana program identifier.
@@ -24,17 +24,17 @@ pub(crate) struct DemoSqlReplayKnownProgramOption {
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_sql_replay_candidates/DemoSqlReplayOptionsPayload.ts"
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_replay_candidates/DemoStoreReplayOptionsPayload.ts"
)]
pub(crate) struct DemoSqlReplayOptionsPayload {
pub(crate) struct DemoStoreReplayOptionsPayload {
/// Active profile name.
pub(crate) active_profile_name: std::string::String,
/// Masked PostgreSQL DSN.
pub(crate) masked_dsn: std::string::String,
/// Safe backend connection descriptor.
pub(crate) connection_descriptor: std::string::String,
/// Maximum rows accepted by one query.
pub(crate) maximum_limit: u32,
/// Program identifiers enumerable from `ks_program_ids`.
pub(crate) known_programs: std::vec::Vec<crate::DemoSqlReplayKnownProgramOption>,
pub(crate) known_programs: std::vec::Vec<crate::DemoStoreReplayKnownProgramOption>,
}
/// UI request for bounded transaction replay candidates.
@@ -42,9 +42,9 @@ pub(crate) struct DemoSqlReplayOptionsPayload {
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_sql_replay_candidates/DemoSqlReplayTransactionRequest.ts"
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_replay_candidates/DemoStoreReplayTransactionRequest.ts"
)]
pub(crate) struct DemoSqlReplayTransactionRequest {
pub(crate) struct DemoStoreReplayTransactionRequest {
/// Optional partial signature search.
pub(crate) signature_contains: std::option::Option<std::string::String>,
/// Optional inclusive minimum slot.
@@ -59,7 +59,7 @@ pub(crate) struct DemoSqlReplayTransactionRequest {
pub(crate) ledger_status: std::option::Option<std::string::String>,
/// Optional exact program id.
pub(crate) program_id: std::option::Option<std::string::String>,
/// Program scope code: any, outer, inner or logs.
/// Program scope code: any, top_level, inner or logs.
pub(crate) program_scope: std::string::String,
/// Optional entity kind: mint, owner or account_key.
pub(crate) entity_kind: std::option::Option<std::string::String>,
@@ -76,9 +76,9 @@ pub(crate) struct DemoSqlReplayTransactionRequest {
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_sql_replay_candidates/DemoSqlReplayTransactionRow.ts"
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_replay_candidates/DemoStoreReplayTransactionRow.ts"
)]
pub(crate) struct DemoSqlReplayTransactionRow {
pub(crate) struct DemoStoreReplayTransactionRow {
/// Canonical transaction signature.
pub(crate) signature: std::string::String,
/// Transaction slot.
@@ -100,13 +100,13 @@ pub(crate) struct DemoSqlReplayTransactionRow {
pub(crate) attempt_count: i32,
/// Number of top-level instructions.
#[ts(type = "number")]
pub(crate) outer_instruction_count: i64,
pub(crate) top_level_instruction_count: i64,
/// Number of inner instructions.
#[ts(type = "number")]
pub(crate) inner_instruction_count: i64,
/// Number of distinct top-level programs.
#[ts(type = "number")]
pub(crate) outer_program_count: i64,
pub(crate) top_level_program_count: i64,
/// Number of distinct inner programs.
#[ts(type = "number")]
pub(crate) inner_program_count: i64,
@@ -119,9 +119,9 @@ pub(crate) struct DemoSqlReplayTransactionRow {
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_sql_replay_candidates/DemoSqlReplayProgramRequest.ts"
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_replay_candidates/DemoStoreReplayProgramRequest.ts"
)]
pub(crate) struct DemoSqlReplayProgramRequest {
pub(crate) struct DemoStoreReplayProgramRequest {
/// Optional partial program id search.
pub(crate) program_id_contains: std::option::Option<std::string::String>,
/// Maximum returned rows.
@@ -133,9 +133,9 @@ pub(crate) struct DemoSqlReplayProgramRequest {
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_sql_replay_candidates/DemoSqlReplayProgramRow.ts"
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_replay_candidates/DemoStoreReplayProgramRow.ts"
)]
pub(crate) struct DemoSqlReplayProgramRow {
pub(crate) struct DemoStoreReplayProgramRow {
/// Optional stable code from `ks_program_ids`.
pub(crate) program_code: std::option::Option<std::string::String>,
/// Program id.
@@ -145,7 +145,7 @@ pub(crate) struct DemoSqlReplayProgramRow {
pub(crate) transaction_count: i64,
/// Number of top-level instruction occurrences.
#[ts(type = "number")]
pub(crate) outer_instruction_count: i64,
pub(crate) top_level_instruction_count: i64,
/// Number of inner instruction occurrences.
#[ts(type = "number")]
pub(crate) inner_instruction_count: i64,
@@ -165,9 +165,9 @@ pub(crate) struct DemoSqlReplayProgramRow {
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_sql_replay_candidates/DemoSqlReplayEntityRequest.ts"
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_replay_candidates/DemoStoreReplayEntityRequest.ts"
)]
pub(crate) struct DemoSqlReplayEntityRequest {
pub(crate) struct DemoStoreReplayEntityRequest {
/// Entity kind: mint, owner or account_key.
pub(crate) entity_kind: std::string::String,
/// Optional partial entity value search.
@@ -181,9 +181,9 @@ pub(crate) struct DemoSqlReplayEntityRequest {
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_sql_replay_candidates/DemoSqlReplayEntityRow.ts"
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_store_replay_candidates/DemoStoreReplayEntityRow.ts"
)]
pub(crate) struct DemoSqlReplayEntityRow {
pub(crate) struct DemoStoreReplayEntityRow {
/// Stable entity kind code.
pub(crate) entity_kind: std::string::String,
/// Mint, owner or account-key address.
@@ -203,7 +203,7 @@ pub(crate) struct DemoSqlReplayEntityRow {
}
/// Writes a bounded replay-candidate CSV file into `./data/exports_csv/`.
pub(crate) async fn export_demo_sql_replay_csv(
pub(crate) async fn export_demo_store_replay_csv(
file_name: std::string::String,
content: std::string::String,
) -> std::result::Result<std::string::String, std::string::String> {
@@ -240,37 +240,40 @@ pub(crate) async fn export_demo_sql_replay_csv(
return std::result::Result::Ok(display_path);
}
/// Loads static browser options from the active PostgreSQL profile.
pub(crate) async fn demo_sql_replay_options(
/// Loads static browser options from the active store.
pub(crate) async fn demo_store_replay_options(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::DemoSqlReplayOptionsPayload, std::string::String> {
) -> std::result::Result<crate::DemoStoreReplayOptionsPayload, std::string::String> {
let profile = state.active_profile().clone();
let options_result = crate::postgres_store_options_from_profile(&profile, false);
let options = match options_result {
let store = match crate::shared_store(state.inner()).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let connection_descriptor = match crate::store_connection_descriptor(&store).await {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mut known_programs =
std::vec::Vec::with_capacity(ks_program_ids::registered_program_ids().len());
for entry in ks_program_ids::registered_program_ids() {
known_programs.push(crate::DemoSqlReplayKnownProgramOption {
known_programs.push(crate::DemoStoreReplayKnownProgramOption {
code: entry.code().to_owned(),
program_id: entry.program_id().to_owned(),
});
}
return std::result::Result::Ok(crate::DemoSqlReplayOptionsPayload {
return std::result::Result::Ok(crate::DemoStoreReplayOptionsPayload {
active_profile_name: profile.name,
masked_dsn: options.masked_dsn(),
connection_descriptor,
maximum_limit: ks_store::MAX_REPLAY_CANDIDATE_ROWS,
known_programs,
});
}
/// Loads bounded transaction replay candidates from PostgreSQL.
pub(crate) async fn load_demo_sql_replay_transactions(
/// Loads bounded transaction replay candidates from the active store.
pub(crate) async fn load_demo_store_replay_transactions(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoSqlReplayTransactionRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoSqlReplayTransactionRow>, std::string::String> {
request: crate::DemoStoreReplayTransactionRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoStoreReplayTransactionRow>, std::string::String> {
let program_scope_result = program_scope_from_code(request.program_scope.as_str());
let program_scope = match program_scope_result {
std::result::Result::Ok(value) => value,
@@ -281,7 +284,7 @@ pub(crate) async fn load_demo_sql_replay_transactions(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let filter_result = ks_store::PostgresReplayTransactionFilter::new(
let filter_result = ks_store::ReplayTransactionFilter::new(
request.signature_contains,
request.min_slot,
request.max_slot,
@@ -298,7 +301,7 @@ pub(crate) async fn load_demo_sql_replay_transactions(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store_result = crate::connect_postgres_store(state.active_profile()).await;
let store_result = crate::shared_store(state.inner()).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
@@ -311,23 +314,23 @@ pub(crate) async fn load_demo_sql_replay_transactions(
tracing::debug!(target: crate::TRACING_TARGET, rows = rows.len(), "loaded replay transaction candidates");
let mut output = std::vec::Vec::with_capacity(rows.len());
for row in rows {
output.push(transaction_row_from_pg(row));
output.push(transaction_row_from_store(row));
}
return std::result::Result::Ok(output);
}
/// Loads bounded program summaries from PostgreSQL.
pub(crate) async fn load_demo_sql_replay_programs(
/// Loads bounded program summaries from the active store.
pub(crate) async fn load_demo_store_replay_programs(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoSqlReplayProgramRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoSqlReplayProgramRow>, std::string::String> {
request: crate::DemoStoreReplayProgramRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoStoreReplayProgramRow>, std::string::String> {
let filter_result =
ks_store::PostgresReplayProgramFilter::new(request.program_id_contains, request.limit);
ks_store::ReplayProgramFilter::new(request.program_id_contains, request.limit);
let filter = match filter_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store_result = crate::connect_postgres_store(state.active_profile()).await;
let store_result = crate::shared_store(state.inner()).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
@@ -340,22 +343,22 @@ pub(crate) async fn load_demo_sql_replay_programs(
tracing::debug!(target: crate::TRACING_TARGET, rows = rows.len(), "loaded replay program summaries");
let mut output = std::vec::Vec::with_capacity(rows.len());
for row in rows {
output.push(program_row_from_pg(row));
output.push(program_row_from_store(row));
}
return std::result::Result::Ok(output);
}
/// Loads bounded mint, owner or account-key summaries from PostgreSQL core tables.
pub(crate) async fn load_demo_sql_replay_entities(
/// Loads bounded mint, owner or account-key summaries from Core facts.
pub(crate) async fn load_demo_store_replay_entities(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoSqlReplayEntityRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoSqlReplayEntityRow>, std::string::String> {
request: crate::DemoStoreReplayEntityRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoStoreReplayEntityRow>, std::string::String> {
let entity_kind_result = entity_kind_from_code(request.entity_kind.as_str());
let entity_kind = match entity_kind_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let filter_result = ks_store::PostgresReplayEntityFilter::new(
let filter_result = ks_store::ReplayEntityFilter::new(
entity_kind,
request.entity_value_contains,
request.limit,
@@ -364,7 +367,7 @@ pub(crate) async fn load_demo_sql_replay_entities(
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
let store_result = crate::connect_postgres_store(state.active_profile()).await;
let store_result = crate::shared_store(state.inner()).await;
let store = match store_result {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
@@ -377,15 +380,15 @@ pub(crate) async fn load_demo_sql_replay_entities(
tracing::debug!(target: crate::TRACING_TARGET, rows = rows.len(), "loaded replay entity summaries");
let mut output = std::vec::Vec::with_capacity(rows.len());
for row in rows {
output.push(entity_row_from_pg(row));
output.push(entity_row_from_store(row));
}
return std::result::Result::Ok(output);
}
fn transaction_row_from_pg(
row: ks_store::PostgresReplayTransactionCandidate,
) -> crate::DemoSqlReplayTransactionRow {
return crate::DemoSqlReplayTransactionRow {
fn transaction_row_from_store(
row: ks_store::ReplayTransactionCandidate,
) -> crate::DemoStoreReplayTransactionRow {
return crate::DemoStoreReplayTransactionRow {
signature: row.signature,
slot: row.slot,
raw_processing_state: row.raw_processing_state,
@@ -395,24 +398,22 @@ fn transaction_row_from_pg(
ledger_status: row.ledger_status,
processor_version: row.processor_version,
attempt_count: row.attempt_count,
outer_instruction_count: row.outer_instruction_count,
top_level_instruction_count: row.top_level_instruction_count,
inner_instruction_count: row.inner_instruction_count,
outer_program_count: row.outer_program_count,
top_level_program_count: row.top_level_program_count,
inner_program_count: row.inner_program_count,
updated_at: row.updated_at,
};
}
fn program_row_from_pg(
row: ks_store::PostgresReplayProgramSummary,
) -> crate::DemoSqlReplayProgramRow {
fn program_row_from_store(row: ks_store::ReplayProgramSummary) -> crate::DemoStoreReplayProgramRow {
let program_code = ks_program_ids::find_registered_program_id(&row.program_id)
.map(|entry| return entry.code().to_owned());
return crate::DemoSqlReplayProgramRow {
return crate::DemoStoreReplayProgramRow {
program_code,
program_id: row.program_id,
transaction_count: row.transaction_count,
outer_instruction_count: row.outer_instruction_count,
top_level_instruction_count: row.top_level_instruction_count,
inner_instruction_count: row.inner_instruction_count,
log_count: row.log_count,
min_slot: row.min_slot,
@@ -420,8 +421,8 @@ fn program_row_from_pg(
};
}
fn entity_row_from_pg(row: ks_store::PostgresReplayEntitySummary) -> crate::DemoSqlReplayEntityRow {
return crate::DemoSqlReplayEntityRow {
fn entity_row_from_store(row: ks_store::ReplayEntitySummary) -> crate::DemoStoreReplayEntityRow {
return crate::DemoStoreReplayEntityRow {
entity_kind: row.entity_kind,
entity_value: row.entity_value,
transaction_count: row.transaction_count,
@@ -480,20 +481,19 @@ async fn available_csv_export_path(
fn program_scope_from_code(
code: &str,
) -> std::result::Result<ks_store::PostgresReplayProgramScope, std::string::String> {
) -> std::result::Result<ks_store::ReplayProgramScope, std::string::String> {
return match code {
"any" => std::result::Result::Ok(ks_store::PostgresReplayProgramScope::Any),
"outer" => std::result::Result::Ok(ks_store::PostgresReplayProgramScope::Outer),
"inner" => std::result::Result::Ok(ks_store::PostgresReplayProgramScope::Inner),
"logs" => std::result::Result::Ok(ks_store::PostgresReplayProgramScope::Logs),
"any" => std::result::Result::Ok(ks_store::ReplayProgramScope::Any),
"top_level" => std::result::Result::Ok(ks_store::ReplayProgramScope::TopLevel),
"inner" => std::result::Result::Ok(ks_store::ReplayProgramScope::Inner),
"logs" => std::result::Result::Ok(ks_store::ReplayProgramScope::Logs),
_ => std::result::Result::Err(format!("unsupported replay program scope: {code}")),
};
}
fn optional_entity_kind_from_code(
code: std::option::Option<&str>,
) -> std::result::Result<std::option::Option<ks_store::PostgresReplayEntityKind>, std::string::String>
{
) -> std::result::Result<std::option::Option<ks_store::ReplayEntityKind>, std::string::String> {
return match code {
std::option::Option::Some(value) => {
let result = entity_kind_from_code(value);
@@ -510,11 +510,11 @@ fn optional_entity_kind_from_code(
fn entity_kind_from_code(
code: &str,
) -> std::result::Result<ks_store::PostgresReplayEntityKind, std::string::String> {
) -> std::result::Result<ks_store::ReplayEntityKind, std::string::String> {
return match code {
"mint" => std::result::Result::Ok(ks_store::PostgresReplayEntityKind::Mint),
"owner" => std::result::Result::Ok(ks_store::PostgresReplayEntityKind::Owner),
"account_key" => std::result::Result::Ok(ks_store::PostgresReplayEntityKind::AccountKey),
"mint" => std::result::Result::Ok(ks_store::ReplayEntityKind::Mint),
"owner" => std::result::Result::Ok(ks_store::ReplayEntityKind::Owner),
"account_key" => std::result::Result::Ok(ks_store::ReplayEntityKind::AccountKey),
_ => std::result::Result::Err(format!("unsupported replay entity kind: {code}")),
};
}
@@ -524,7 +524,7 @@ mod tests {
#[test]
fn program_scope_parser_accepts_logs() {
let result = super::program_scope_from_code("logs");
assert_eq!(result, std::result::Result::Ok(ks_store::PostgresReplayProgramScope::Logs));
assert_eq!(result, std::result::Result::Ok(ks_store::ReplayProgramScope::Logs));
}
#[test]
@@ -551,16 +551,16 @@ mod tests {
#[test]
fn program_row_exposes_registered_code() {
let row = ks_store::PostgresReplayProgramSummary {
let row = ks_store::ReplayProgramSummary {
program_id: ks_program_ids::SYSTEM_PROGRAM_ID.to_owned(),
transaction_count: 1,
outer_instruction_count: 1,
top_level_instruction_count: 1,
inner_instruction_count: 0,
log_count: 1,
min_slot: 1,
max_slot: 1,
};
let converted = super::program_row_from_pg(row);
let converted = super::program_row_from_store(row);
assert_eq!(converted.program_code.as_deref(), std::option::Option::Some("system"));
}
}

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_ws.rs
// version: 23
// version: 24
//! Standard Solana WebSocket demo commands backed by `ks_onchain_transport::WsSession`.
@@ -1031,7 +1031,7 @@ mod tests {
<crate::DemoWsUnsubscribeRequest as TS>::decl(&config),
<crate::DemoBackfillProgressPayload as TS>::decl(&config),
<crate::DemoBackfillSummaryPayload as TS>::decl(&config),
<crate::DemoSqlTableSnapshot as TS>::decl(&config),
<crate::DemoStoreResourceSnapshot as TS>::decl(&config),
];
for declaration in declarations {
assert!(!declaration.contains("bigint"));

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/lib.rs
// version: 43
// version: 47
//! Tauri desktop demo application for `khadhroony-bot3`.
@@ -24,11 +24,11 @@ mod demo_http;
mod demo_spl_ata;
mod demo_spl_token;
mod demo_spl_token_2022;
mod demo_sql_common;
mod demo_sql_diag;
mod demo_sql_pg_core;
mod demo_sql_pg_raw;
mod demo_sql_replay_candidates;
mod demo_store_common;
mod demo_store_core;
mod demo_store_diag;
mod demo_store_raw;
mod demo_store_replay_candidates;
mod demo_transport;
mod demo_wallet;
mod demo_ws;
@@ -147,7 +147,7 @@ pub(crate) use self::demo_decode_replay::demo_decode_replay_diagnostics;
pub(crate) use self::demo_decode_replay::demo_decode_replay_execute;
/// Returns available decoders and default replay bounds.
pub(crate) use self::demo_decode_replay::demo_decode_replay_options;
/// Readiness report for one Devnet profile PostgreSQL store.
/// Backend-agnostic readiness report for one Devnet profile store.
pub(crate) use self::demo_devnet_common::DemoExecutionDevnetStoreReadinessPayload;
/// Restores the shared single-execution state flag when a Devnet run finishes.
pub(crate) use self::demo_devnet_common::DemoExecutionRunGuard;
@@ -315,58 +315,60 @@ pub(crate) use self::demo_spl_token_2022::DemoSplToken2022FixturePayload;
pub(crate) use self::demo_spl_token_2022::demo_execution_spl_token_2022_execute;
/// Loads public Token-2022 fixture values without reading private key bytes.
pub(crate) use self::demo_spl_token_2022::demo_spl_token_2022_fixture;
/// UI-safe SQL table diagnostic snapshot.
pub(crate) use self::demo_sql_common::DemoSqlTableSnapshot;
/// Connects to the configured PostgreSQL store.
pub(crate) use self::demo_sql_common::connect_postgres_store;
/// UI-safe logical store resource diagnostic snapshot.
pub(crate) use self::demo_store_common::DemoStoreResourceSnapshot;
/// Formats diagnostic statuses.
pub(crate) use self::demo_sql_common::debug_status;
/// Initializes the PostgreSQL schema during startup.
pub(crate) use self::demo_sql_common::initialize_postgres_schema_for_startup;
/// Builds PostgreSQL options from the active profile.
pub(crate) use self::demo_sql_common::postgres_store_options_from_profile;
/// Converts one PostgreSQL table diagnostic.
pub(crate) use self::demo_sql_common::table_snapshot_from_pg;
/// Converts PostgreSQL table diagnostics.
pub(crate) use self::demo_sql_common::table_snapshots_from_pg;
/// SQL diagnostic payload.
pub(crate) use self::demo_sql_diag::DemoSqlDiagPayload;
/// Loads read-only SQL diagnostics from the active profile.
pub(crate) use self::demo_sql_diag::load_demo_sql_diag;
/// PostgreSQL core-table payload.
pub(crate) use self::demo_sql_pg_core::DemoSqlPgCorePayload;
/// Loads read-only core table diagnostics from PostgreSQL.
pub(crate) use self::demo_sql_pg_core::load_demo_sql_pg_core;
/// PostgreSQL raw-table payload.
pub(crate) use self::demo_sql_pg_raw::DemoSqlPgRawPayload;
/// Loads read-only raw table diagnostics from PostgreSQL.
pub(crate) use self::demo_sql_pg_raw::load_demo_sql_pg_raw;
/// SQL replay entity request.
pub(crate) use self::demo_sql_replay_candidates::DemoSqlReplayEntityRequest;
/// SQL replay entity row.
pub(crate) use self::demo_sql_replay_candidates::DemoSqlReplayEntityRow;
pub(crate) use self::demo_store_common::debug_status;
/// Opens and verifies the configured store during startup.
pub(crate) use self::demo_store_common::initialize_store_for_startup;
/// Opens the configured backend-agnostic store.
pub(crate) use self::demo_store_common::open_store;
/// Clones the persistent application store.
pub(crate) use self::demo_store_common::shared_store;
/// Returns the safe connection descriptor exposed by the active store backend.
pub(crate) use self::demo_store_common::store_connection_descriptor;
/// Converts one logical store resource diagnostic.
pub(crate) use self::demo_store_common::store_resource_snapshot;
/// Converts logical store resource diagnostics.
pub(crate) use self::demo_store_common::store_resource_snapshots;
/// Backend-agnostic Core store diagnostic payload.
pub(crate) use self::demo_store_core::DemoStoreCorePayload;
/// Loads read-only Core resource diagnostics from the active store.
pub(crate) use self::demo_store_core::load_demo_store_core;
/// Backend-agnostic store diagnostic payload.
pub(crate) use self::demo_store_diag::DemoStoreDiagPayload;
/// Loads read-only Store diagnostics from the active profile.
pub(crate) use self::demo_store_diag::load_demo_store_diag;
/// Backend-agnostic raw store diagnostic payload.
pub(crate) use self::demo_store_raw::DemoStoreRawPayload;
/// Loads read-only raw resource diagnostics from the active store.
pub(crate) use self::demo_store_raw::load_demo_store_raw;
/// Store replay entity request.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayEntityRequest;
/// Store replay entity row.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayEntityRow;
/// Known program option.
pub(crate) use self::demo_sql_replay_candidates::DemoSqlReplayKnownProgramOption;
/// SQL replay options payload.
pub(crate) use self::demo_sql_replay_candidates::DemoSqlReplayOptionsPayload;
/// SQL replay program request.
pub(crate) use self::demo_sql_replay_candidates::DemoSqlReplayProgramRequest;
/// SQL replay program row.
pub(crate) use self::demo_sql_replay_candidates::DemoSqlReplayProgramRow;
/// SQL replay transaction request.
pub(crate) use self::demo_sql_replay_candidates::DemoSqlReplayTransactionRequest;
/// SQL replay transaction row.
pub(crate) use self::demo_sql_replay_candidates::DemoSqlReplayTransactionRow;
/// Loads static browser options from the active PostgreSQL profile.
pub(crate) use self::demo_sql_replay_candidates::demo_sql_replay_options;
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayKnownProgramOption;
/// Store replay options payload.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayOptionsPayload;
/// Store replay program request.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayProgramRequest;
/// Store replay program row.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayProgramRow;
/// Store replay transaction request.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayTransactionRequest;
/// Store replay transaction row.
pub(crate) use self::demo_store_replay_candidates::DemoStoreReplayTransactionRow;
/// Loads static replay browser options from the active store profile.
pub(crate) use self::demo_store_replay_candidates::demo_store_replay_options;
/// Writes a bounded replay-candidate CSV file into `./data/exports_csv/`.
pub(crate) use self::demo_sql_replay_candidates::export_demo_sql_replay_csv;
/// Loads bounded mint, owner or account-key summaries from PostgreSQL core tables.
pub(crate) use self::demo_sql_replay_candidates::load_demo_sql_replay_entities;
/// Loads bounded program summaries from PostgreSQL.
pub(crate) use self::demo_sql_replay_candidates::load_demo_sql_replay_programs;
/// Loads bounded transaction replay candidates from PostgreSQL.
pub(crate) use self::demo_sql_replay_candidates::load_demo_sql_replay_transactions;
pub(crate) use self::demo_store_replay_candidates::export_demo_store_replay_csv;
/// Loads bounded mint, owner or account-key summaries from Core store resources.
pub(crate) use self::demo_store_replay_candidates::load_demo_store_replay_entities;
/// Loads bounded program summaries from the active store.
pub(crate) use self::demo_store_replay_candidates::load_demo_store_replay_programs;
/// Loads bounded transaction replay candidates from the active store.
pub(crate) use self::demo_store_replay_candidates::load_demo_store_replay_transactions;
/// UI-safe endpoint role shared by HTTP and WebSocket diagnostics.
pub(crate) use self::demo_transport::DemoEndpointRolePayload;
/// Exact public SOL balance projected by the wallet demo.

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/splash.rs
// version: 5
// version: 6
//! Splash-window payloads and startup sequencing helpers.
@@ -112,7 +112,7 @@ pub(crate) async fn splash_frontend_ready(
std::option::Option::Some("success"),
std::option::Option::None,
);
crate::initialize_postgres_schema_for_startup(state, &window).await;
crate::initialize_store_for_startup(state, &window).await;
crate::emit_splash_order(
&window,
"add_msg",

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/tauri.rs
// version: 44
// version: 46
//! Tauri runtime assembly and private command wrappers.
@@ -71,18 +71,18 @@ pub fn run() -> ks_core::Result<()> {
demo_decode_replay_cancel,
demo_decode_replay_diagnostics,
demo_decode_replay_annotations,
open_demo_sql_diag_window,
load_demo_sql_diag,
open_demo_sql_pg_raw_window,
load_demo_sql_pg_raw,
open_demo_sql_pg_core_window,
load_demo_sql_pg_core,
open_demo_sql_replay_candidates_window,
export_demo_sql_replay_csv,
demo_sql_replay_options,
load_demo_sql_replay_transactions,
load_demo_sql_replay_programs,
load_demo_sql_replay_entities,
open_demo_store_diag_window,
load_demo_store_diag,
open_demo_store_raw_window,
load_demo_store_raw,
open_demo_store_core_window,
load_demo_store_core,
open_demo_store_replay_candidates_window,
export_demo_store_replay_csv,
demo_store_replay_options,
load_demo_store_replay_transactions,
load_demo_store_replay_programs,
load_demo_store_replay_entities,
open_demo_execution_solana_core_window,
demo_execution_devnet_prepare_profile,
demo_execution_solana_core_options,
@@ -518,111 +518,111 @@ async fn demo_decode_replay_annotations(
}
#[tauri::command]
fn open_demo_sql_diag_window(
fn open_demo_store_diag_window(
app_handle: tauri::AppHandle,
) -> std::result::Result<(), std::string::String> {
return open_or_focus_demo_window(
app_handle,
"demo_sql_diag",
"demo_sql_diag.html",
"SQL diagnostics",
"demo_store_diag",
"demo_store_diag.html",
"Store diagnostics",
);
}
#[tauri::command]
async fn load_demo_sql_diag(
async fn load_demo_store_diag(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::DemoSqlDiagPayload, std::string::String> {
return crate::load_demo_sql_diag(state).await;
) -> std::result::Result<crate::DemoStoreDiagPayload, std::string::String> {
return crate::load_demo_store_diag(state).await;
}
#[tauri::command]
fn open_demo_sql_pg_raw_window(
fn open_demo_store_raw_window(
app_handle: tauri::AppHandle,
) -> std::result::Result<(), std::string::String> {
return open_or_focus_demo_window(
app_handle,
"demo_sql_pg_raw",
"demo_sql_pg_raw.html",
"PostgreSQL canonical acquisition",
"demo_store_raw",
"demo_store_raw.html",
"Raw store",
);
}
#[tauri::command]
async fn load_demo_sql_pg_raw(
async fn load_demo_store_raw(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::DemoSqlPgRawPayload, std::string::String> {
return crate::load_demo_sql_pg_raw(state).await;
) -> std::result::Result<crate::DemoStoreRawPayload, std::string::String> {
return crate::load_demo_store_raw(state).await;
}
#[tauri::command]
fn open_demo_sql_pg_core_window(
fn open_demo_store_core_window(
app_handle: tauri::AppHandle,
) -> std::result::Result<(), std::string::String> {
return open_or_focus_demo_window(
app_handle,
"demo_sql_pg_core",
"demo_sql_pg_core.html",
"PostgreSQL core store",
"demo_store_core",
"demo_store_core.html",
"Core store",
);
}
#[tauri::command]
async fn load_demo_sql_pg_core(
async fn load_demo_store_core(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::DemoSqlPgCorePayload, std::string::String> {
return crate::load_demo_sql_pg_core(state).await;
) -> std::result::Result<crate::DemoStoreCorePayload, std::string::String> {
return crate::load_demo_store_core(state).await;
}
#[tauri::command]
fn open_demo_sql_replay_candidates_window(
fn open_demo_store_replay_candidates_window(
app_handle: tauri::AppHandle,
) -> std::result::Result<(), std::string::String> {
return open_or_focus_demo_window(
app_handle,
"demo_sql_replay_candidates",
"demo_sql_replay_candidates.html",
"SQL replay candidates",
"demo_store_replay_candidates",
"demo_store_replay_candidates.html",
"Store replay candidates",
);
}
#[tauri::command]
async fn export_demo_sql_replay_csv(
async fn export_demo_store_replay_csv(
file_name: std::string::String,
content: std::string::String,
) -> std::result::Result<std::string::String, std::string::String> {
return crate::export_demo_sql_replay_csv(file_name, content).await;
return crate::export_demo_store_replay_csv(file_name, content).await;
}
#[tauri::command]
async fn demo_sql_replay_options(
async fn demo_store_replay_options(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::DemoSqlReplayOptionsPayload, std::string::String> {
return crate::demo_sql_replay_options(state).await;
) -> std::result::Result<crate::DemoStoreReplayOptionsPayload, std::string::String> {
return crate::demo_store_replay_options(state).await;
}
#[tauri::command]
async fn load_demo_sql_replay_transactions(
async fn load_demo_store_replay_transactions(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoSqlReplayTransactionRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoSqlReplayTransactionRow>, std::string::String> {
return crate::load_demo_sql_replay_transactions(state, request).await;
request: crate::DemoStoreReplayTransactionRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoStoreReplayTransactionRow>, std::string::String> {
return crate::load_demo_store_replay_transactions(state, request).await;
}
#[tauri::command]
async fn load_demo_sql_replay_programs(
async fn load_demo_store_replay_programs(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoSqlReplayProgramRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoSqlReplayProgramRow>, std::string::String> {
return crate::load_demo_sql_replay_programs(state, request).await;
request: crate::DemoStoreReplayProgramRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoStoreReplayProgramRow>, std::string::String> {
return crate::load_demo_store_replay_programs(state, request).await;
}
#[tauri::command]
async fn load_demo_sql_replay_entities(
async fn load_demo_store_replay_entities(
state: tauri::State<'_, crate::AppState>,
request: crate::DemoSqlReplayEntityRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoSqlReplayEntityRow>, std::string::String> {
return crate::load_demo_sql_replay_entities(state, request).await;
request: crate::DemoStoreReplayEntityRequest,
) -> std::result::Result<std::vec::Vec<crate::DemoStoreReplayEntityRow>, std::string::String> {
return crate::load_demo_store_replay_entities(state, request).await;
}
#[tauri::command]