mirror of
https://github.com/haexhub/haex-hub.git
synced 2025-12-16 22:20:51 +01:00
adjust drizzle backend.
return array of arrays handle table names with quotes
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@ -26,4 +26,5 @@ dist-ssr
|
|||||||
src-tauri/target
|
src-tauri/target
|
||||||
nogit*
|
nogit*
|
||||||
.claude
|
.claude
|
||||||
.output
|
.output
|
||||||
|
target
|
||||||
665
pnpm-lock.yaml
generated
665
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -85,7 +85,8 @@ impl ColumnInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_safe_identifier(name: &str) -> bool {
|
fn is_safe_identifier(name: &str) -> bool {
|
||||||
!name.is_empty() && name.chars().all(|c| c.is_alphanumeric() || c == '_')
|
// Allow alphanumeric characters, underscores, and hyphens (for extension names like "nuxt-app")
|
||||||
|
!name.is_empty() && name.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '-')
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Richtet CRDT-Trigger für eine einzelne Tabelle ein.
|
/// Richtet CRDT-Trigger für eine einzelne Tabelle ein.
|
||||||
|
|||||||
@ -89,8 +89,15 @@ pub fn parse_single_statement(sql: &str) -> Result<Statement, DatabaseError> {
|
|||||||
/// Utility für SQL-Parsing - parst mehrere SQL-Statements
|
/// Utility für SQL-Parsing - parst mehrere SQL-Statements
|
||||||
pub fn parse_sql_statements(sql: &str) -> Result<Vec<Statement>, DatabaseError> {
|
pub fn parse_sql_statements(sql: &str) -> Result<Vec<Statement>, DatabaseError> {
|
||||||
let dialect = SQLiteDialect {};
|
let dialect = SQLiteDialect {};
|
||||||
Parser::parse_sql(&dialect, sql).map_err(|e| DatabaseError::ParseError {
|
|
||||||
reason: e.to_string(),
|
// Normalize whitespace: replace multiple whitespaces (including newlines, tabs) with single space
|
||||||
|
let normalized_sql = sql
|
||||||
|
.split_whitespace()
|
||||||
|
.collect::<Vec<&str>>()
|
||||||
|
.join(" ");
|
||||||
|
|
||||||
|
Parser::parse_sql(&dialect, &normalized_sql).map_err(|e| DatabaseError::ParseError {
|
||||||
|
reason: format!("Failed to parse SQL: {}", e),
|
||||||
sql: sql.to_string(),
|
sql: sql.to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,7 +64,13 @@ impl SqlExecutor {
|
|||||||
|
|
||||||
// Trigger-Logik für CREATE TABLE
|
// Trigger-Logik für CREATE TABLE
|
||||||
if let Statement::CreateTable(create_table_details) = statement {
|
if let Statement::CreateTable(create_table_details) = statement {
|
||||||
let table_name_str = create_table_details.name.to_string();
|
let raw_name = create_table_details.name.to_string();
|
||||||
|
// Remove quotes from table name
|
||||||
|
let table_name_str = raw_name
|
||||||
|
.trim_matches('"')
|
||||||
|
.trim_matches('`')
|
||||||
|
.to_string();
|
||||||
|
eprintln!("DEBUG: Setting up triggers for table: {}", table_name_str);
|
||||||
trigger::setup_triggers_for_table(tx, &table_name_str, false)?;
|
trigger::setup_triggers_for_table(tx, &table_name_str, false)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +164,13 @@ impl SqlExecutor {
|
|||||||
|
|
||||||
// Trigger-Logik für CREATE TABLE
|
// Trigger-Logik für CREATE TABLE
|
||||||
if let Statement::CreateTable(create_table_details) = statement {
|
if let Statement::CreateTable(create_table_details) = statement {
|
||||||
let table_name_str = create_table_details.name.to_string();
|
let raw_name = create_table_details.name.to_string();
|
||||||
|
// Remove quotes from table name
|
||||||
|
let table_name_str = raw_name
|
||||||
|
.trim_matches('"')
|
||||||
|
.trim_matches('`')
|
||||||
|
.to_string();
|
||||||
|
eprintln!("DEBUG: Setting up triggers for table (RETURNING): {}", table_name_str);
|
||||||
trigger::setup_triggers_for_table(tx, &table_name_str, false)?;
|
trigger::setup_triggers_for_table(tx, &table_name_str, false)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ use crate::crdt::transformer::CrdtTransformer;
|
|||||||
use crate::crdt::trigger;
|
use crate::crdt::trigger;
|
||||||
use crate::database::core::{parse_sql_statements, with_connection, ValueConverter};
|
use crate::database::core::{parse_sql_statements, with_connection, ValueConverter};
|
||||||
use crate::database::error::DatabaseError;
|
use crate::database::error::DatabaseError;
|
||||||
|
use crate::extension::database::executor::SqlExecutor;
|
||||||
use crate::extension::error::ExtensionError;
|
use crate::extension::error::ExtensionError;
|
||||||
use crate::extension::permissions::validator::SqlPermissionValidator;
|
use crate::extension::permissions::validator::SqlPermissionValidator;
|
||||||
use crate::AppState;
|
use crate::AppState;
|
||||||
@ -110,7 +111,7 @@ pub async fn extension_sql_execute(
|
|||||||
public_key: String,
|
public_key: String,
|
||||||
name: String,
|
name: String,
|
||||||
state: State<'_, AppState>,
|
state: State<'_, AppState>,
|
||||||
) -> Result<Vec<String>, ExtensionError> {
|
) -> Result<Vec<Vec<JsonValue>>, ExtensionError> {
|
||||||
// Get extension to retrieve its ID
|
// Get extension to retrieve its ID
|
||||||
let extension = state
|
let extension = state
|
||||||
.extension_manager
|
.extension_manager
|
||||||
@ -129,58 +130,87 @@ pub async fn extension_sql_execute(
|
|||||||
// SQL parsing
|
// SQL parsing
|
||||||
let mut ast_vec = parse_sql_statements(sql)?;
|
let mut ast_vec = parse_sql_statements(sql)?;
|
||||||
|
|
||||||
|
if ast_vec.len() != 1 {
|
||||||
|
return Err(ExtensionError::Database {
|
||||||
|
source: DatabaseError::ExecutionError {
|
||||||
|
sql: sql.to_string(),
|
||||||
|
reason: "extension_sql_execute should only receive a single SQL statement"
|
||||||
|
.to_string(),
|
||||||
|
table: None,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut statement = ast_vec.pop().unwrap();
|
||||||
|
|
||||||
|
// Check if statement has RETURNING clause
|
||||||
|
let has_returning = crate::database::core::statement_has_returning(&statement);
|
||||||
|
|
||||||
// Database operation
|
// Database operation
|
||||||
with_connection(&state.db, |conn| {
|
with_connection(&state.db, |conn| {
|
||||||
let tx = conn.transaction().map_err(DatabaseError::from)?;
|
let tx = conn.transaction().map_err(DatabaseError::from)?;
|
||||||
|
|
||||||
let transformer = CrdtTransformer::new();
|
let transformer = CrdtTransformer::new();
|
||||||
let executor = StatementExecutor::new(&tx);
|
|
||||||
|
// Get HLC service reference
|
||||||
|
let hlc_service = state.hlc.lock().map_err(|_| DatabaseError::MutexPoisoned {
|
||||||
|
reason: "Failed to lock HLC service".to_string(),
|
||||||
|
})?;
|
||||||
|
|
||||||
// Generate HLC timestamp
|
// Generate HLC timestamp
|
||||||
let hlc_timestamp = state
|
let hlc_timestamp = hlc_service
|
||||||
.hlc
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.new_timestamp_and_persist(&tx)
|
.new_timestamp_and_persist(&tx)
|
||||||
.map_err(|e| DatabaseError::HlcError {
|
.map_err(|e| DatabaseError::HlcError {
|
||||||
reason: e.to_string(),
|
reason: e.to_string(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Transform statements
|
// Transform statement
|
||||||
let mut modified_schema_tables = HashSet::new();
|
transformer.transform_execute_statement(&mut statement, &hlc_timestamp)?;
|
||||||
for statement in &mut ast_vec {
|
|
||||||
if let Some(table_name) =
|
|
||||||
transformer.transform_execute_statement(statement, &hlc_timestamp)?
|
|
||||||
{
|
|
||||||
modified_schema_tables.insert(table_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert parameters
|
// Convert parameters to references
|
||||||
let sql_values = ValueConverter::convert_params(¶ms)?;
|
let sql_values = ValueConverter::convert_params(¶ms)?;
|
||||||
|
let param_refs: Vec<&dyn rusqlite::ToSql> = sql_values.iter().map(|v| v as &dyn rusqlite::ToSql).collect();
|
||||||
|
|
||||||
// Execute statements
|
let result = if has_returning {
|
||||||
for statement in ast_vec {
|
// Use query_internal for statements with RETURNING
|
||||||
executor.execute_statement_with_params(&statement, &sql_values)?;
|
let (_, rows) = SqlExecutor::query_internal_typed(&tx, &hlc_service, &statement.to_string(), ¶m_refs)?;
|
||||||
|
rows
|
||||||
|
} else {
|
||||||
|
// Use execute_internal for statements without RETURNING
|
||||||
|
SqlExecutor::execute_internal_typed(&tx, &hlc_service, &statement.to_string(), ¶m_refs)?;
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
if let Statement::CreateTable(create_table_details) = statement {
|
// Handle CREATE TABLE trigger setup
|
||||||
let table_name_str = create_table_details.name.to_string();
|
if let Statement::CreateTable(ref create_table_details) = statement {
|
||||||
println!(
|
// Extract table name and remove quotes (both " and `)
|
||||||
"Table '{}' created by extension, setting up CRDT triggers...",
|
let raw_name = create_table_details.name.to_string();
|
||||||
table_name_str
|
println!("DEBUG: Raw table name from AST: {:?}", raw_name);
|
||||||
);
|
println!("DEBUG: Raw table name chars: {:?}", raw_name.chars().collect::<Vec<_>>());
|
||||||
trigger::setup_triggers_for_table(&tx, &table_name_str, false)?;
|
|
||||||
println!(
|
let table_name_str = raw_name
|
||||||
"Triggers for table '{}' successfully created.",
|
.trim_matches('"')
|
||||||
table_name_str
|
.trim_matches('`')
|
||||||
);
|
.to_string();
|
||||||
}
|
|
||||||
|
println!("DEBUG: Cleaned table name: {:?}", table_name_str);
|
||||||
|
println!("DEBUG: Cleaned table name chars: {:?}", table_name_str.chars().collect::<Vec<_>>());
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Table '{}' created by extension, setting up CRDT triggers...",
|
||||||
|
table_name_str
|
||||||
|
);
|
||||||
|
trigger::setup_triggers_for_table(&tx, &table_name_str, false)?;
|
||||||
|
println!(
|
||||||
|
"Triggers for table '{}' successfully created.",
|
||||||
|
table_name_str
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit transaction
|
// Commit transaction
|
||||||
tx.commit().map_err(DatabaseError::from)?;
|
tx.commit().map_err(DatabaseError::from)?;
|
||||||
|
|
||||||
Ok(modified_schema_tables.into_iter().collect())
|
Ok(result)
|
||||||
})
|
})
|
||||||
.map_err(ExtensionError::from)
|
.map_err(ExtensionError::from)
|
||||||
}
|
}
|
||||||
@ -192,7 +222,7 @@ pub async fn extension_sql_select(
|
|||||||
public_key: String,
|
public_key: String,
|
||||||
name: String,
|
name: String,
|
||||||
state: State<'_, AppState>,
|
state: State<'_, AppState>,
|
||||||
) -> Result<Vec<JsonValue>, ExtensionError> {
|
) -> Result<Vec<Vec<JsonValue>>, ExtensionError> {
|
||||||
// Get extension to retrieve its ID
|
// Get extension to retrieve its ID
|
||||||
let extension = state
|
let extension = state
|
||||||
.extension_manager
|
.extension_manager
|
||||||
@ -229,10 +259,9 @@ pub async fn extension_sql_select(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Database operation
|
// Database operation - return Vec<Vec<JsonValue>> like sql_select_with_crdt
|
||||||
with_connection(&state.db, |conn| {
|
with_connection(&state.db, |conn| {
|
||||||
let sql_params = ValueConverter::convert_params(¶ms)?;
|
let sql_params = ValueConverter::convert_params(¶ms)?;
|
||||||
// Hard Delete: Keine SELECT-Transformation mehr nötig
|
|
||||||
let stmt_to_execute = ast_vec.pop().unwrap();
|
let stmt_to_execute = ast_vec.pop().unwrap();
|
||||||
let transformed_sql = stmt_to_execute.to_string();
|
let transformed_sql = stmt_to_execute.to_string();
|
||||||
|
|
||||||
@ -245,51 +274,34 @@ pub async fn extension_sql_select(
|
|||||||
table: None,
|
table: None,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let column_names: Vec<String> = prepared_stmt
|
let num_columns = prepared_stmt.column_count();
|
||||||
.column_names()
|
let mut rows = prepared_stmt
|
||||||
.into_iter()
|
.query(params_from_iter(sql_params.iter()))
|
||||||
.map(|s| s.to_string())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let rows = prepared_stmt
|
|
||||||
.query_map(params_from_iter(sql_params.iter()), |row| {
|
|
||||||
row_to_json_value(row, &column_names)
|
|
||||||
})
|
|
||||||
.map_err(|e| DatabaseError::QueryError {
|
.map_err(|e| DatabaseError::QueryError {
|
||||||
reason: e.to_string(),
|
reason: e.to_string(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let mut results = Vec::new();
|
let mut result_vec: Vec<Vec<JsonValue>> = Vec::new();
|
||||||
for row_result in rows {
|
|
||||||
results.push(row_result.map_err(|e| DatabaseError::RowProcessingError {
|
while let Some(row) = rows.next().map_err(|e| DatabaseError::QueryError {
|
||||||
reason: e.to_string(),
|
reason: e.to_string(),
|
||||||
})?);
|
})? {
|
||||||
|
let mut row_values: Vec<JsonValue> = Vec::new();
|
||||||
|
for i in 0..num_columns {
|
||||||
|
let value_ref = row.get_ref(i).map_err(|e| DatabaseError::QueryError {
|
||||||
|
reason: e.to_string(),
|
||||||
|
})?;
|
||||||
|
let json_value = crate::database::core::convert_value_ref_to_json(value_ref)?;
|
||||||
|
row_values.push(json_value);
|
||||||
|
}
|
||||||
|
result_vec.push(row_values);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(results)
|
Ok(result_vec)
|
||||||
})
|
})
|
||||||
.map_err(ExtensionError::from)
|
.map_err(ExtensionError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Konvertiert eine SQLite-Zeile zu JSON
|
|
||||||
fn row_to_json_value(
|
|
||||||
row: &rusqlite::Row,
|
|
||||||
columns: &[String],
|
|
||||||
) -> Result<JsonValue, rusqlite::Error> {
|
|
||||||
let mut map = serde_json::Map::new();
|
|
||||||
for (i, col_name) in columns.iter().enumerate() {
|
|
||||||
let value = row.get::<usize, rusqlite::types::Value>(i)?;
|
|
||||||
let json_value = match value {
|
|
||||||
rusqlite::types::Value::Null => JsonValue::Null,
|
|
||||||
rusqlite::types::Value::Integer(i) => json!(i),
|
|
||||||
rusqlite::types::Value::Real(f) => json!(f),
|
|
||||||
rusqlite::types::Value::Text(s) => json!(s),
|
|
||||||
rusqlite::types::Value::Blob(blob) => json!(blob.to_vec()),
|
|
||||||
};
|
|
||||||
map.insert(col_name.clone(), json_value);
|
|
||||||
}
|
|
||||||
Ok(JsonValue::Object(map))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Validiert Parameter gegen SQL-Platzhalter
|
/// Validiert Parameter gegen SQL-Platzhalter
|
||||||
fn validate_params(sql: &str, params: &[JsonValue]) -> Result<(), DatabaseError> {
|
fn validate_params(sql: &str, params: &[JsonValue]) -> Result<(), DatabaseError> {
|
||||||
|
|||||||
@ -343,9 +343,8 @@ pub async fn load_dev_extension(
|
|||||||
|
|
||||||
let manifest: ExtensionManifest = serde_json::from_str(&manifest_content)?;
|
let manifest: ExtensionManifest = serde_json::from_str(&manifest_content)?;
|
||||||
|
|
||||||
// 4. Generate a unique ID for dev extension: dev_<public_key_first_8>_<name>
|
// 4. Generate a unique ID for dev extension: dev_<public_key>_<name>
|
||||||
let key_prefix = manifest.public_key.chars().take(8).collect::<String>();
|
let extension_id = format!("dev_{}_{}", manifest.public_key, manifest.name);
|
||||||
let extension_id = format!("dev_{}_{}", key_prefix, manifest.name);
|
|
||||||
|
|
||||||
// 5. Check if dev extension already exists (allow reload)
|
// 5. Check if dev extension already exists (allow reload)
|
||||||
if let Some(existing) = state
|
if let Some(existing) = state
|
||||||
|
|||||||
@ -197,6 +197,30 @@ impl PermissionManager {
|
|||||||
action: Action,
|
action: Action,
|
||||||
table_name: &str,
|
table_name: &str,
|
||||||
) -> Result<(), ExtensionError> {
|
) -> Result<(), ExtensionError> {
|
||||||
|
// Remove quotes from table name if present (from SDK's getTableName())
|
||||||
|
let clean_table_name = table_name.trim_matches('"');
|
||||||
|
|
||||||
|
// Auto-allow: Extensions have full access to their own tables
|
||||||
|
// Table format: {publicKey}__{extensionName}__{tableName}
|
||||||
|
// Extension ID format: dev_{publicKey}_{extensionName} or {publicKey}_{extensionName}
|
||||||
|
|
||||||
|
// Get the extension to check if this is its own table
|
||||||
|
let extension = app_state
|
||||||
|
.extension_manager
|
||||||
|
.get_extension(extension_id)
|
||||||
|
.ok_or_else(|| ExtensionError::ValidationError {
|
||||||
|
reason: format!("Extension with ID {} not found", extension_id),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Build expected table prefix: {publicKey}__{extensionName}__
|
||||||
|
let expected_prefix = format!("{}__{}__", extension.manifest.public_key, extension.manifest.name);
|
||||||
|
|
||||||
|
if clean_table_name.starts_with(&expected_prefix) {
|
||||||
|
// This is the extension's own table - auto-allow
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not own table - check explicit permissions
|
||||||
let permissions = Self::get_permissions(app_state, extension_id).await?;
|
let permissions = Self::get_permissions(app_state, extension_id).await?;
|
||||||
|
|
||||||
let has_permission = permissions
|
let has_permission = permissions
|
||||||
@ -205,7 +229,7 @@ impl PermissionManager {
|
|||||||
.filter(|perm| perm.resource_type == ResourceType::Db)
|
.filter(|perm| perm.resource_type == ResourceType::Db)
|
||||||
.filter(|perm| perm.action == action) // action ist nicht mehr Option
|
.filter(|perm| perm.action == action) // action ist nicht mehr Option
|
||||||
.any(|perm| {
|
.any(|perm| {
|
||||||
if perm.target != "*" && perm.target != table_name {
|
if perm.target != "*" && perm.target != clean_table_name {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
|
|||||||
@ -3,6 +3,8 @@ export default defineAppConfig({
|
|||||||
colors: {
|
colors: {
|
||||||
primary: 'sky',
|
primary: 'sky',
|
||||||
secondary: 'fuchsia',
|
secondary: 'fuchsia',
|
||||||
|
warning: 'yellow',
|
||||||
|
danger: 'red',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@ -115,6 +115,7 @@
|
|||||||
:source-height="window.sourceHeight"
|
:source-height="window.sourceHeight"
|
||||||
:is-opening="window.isOpening"
|
:is-opening="window.isOpening"
|
||||||
:is-closing="window.isClosing"
|
:is-closing="window.isClosing"
|
||||||
|
:warning-level="window.type === 'extension' && availableExtensions.find(ext => ext.id === window.sourceId)?.devServerUrl ? 'warning' : undefined"
|
||||||
class="no-swipe"
|
class="no-swipe"
|
||||||
@close="windowManager.closeWindow(window.id)"
|
@close="windowManager.closeWindow(window.id)"
|
||||||
@minimize="windowManager.minimizeWindow(window.id)"
|
@minimize="windowManager.minimizeWindow(window.id)"
|
||||||
@ -164,6 +165,7 @@
|
|||||||
:source-height="window.sourceHeight"
|
:source-height="window.sourceHeight"
|
||||||
:is-opening="window.isOpening"
|
:is-opening="window.isOpening"
|
||||||
:is-closing="window.isClosing"
|
:is-closing="window.isClosing"
|
||||||
|
:warning-level="window.type === 'extension' && availableExtensions.find(ext => ext.id === window.sourceId)?.devServerUrl ? 'warning' : undefined"
|
||||||
class="no-swipe"
|
class="no-swipe"
|
||||||
@close="windowManager.closeWindow(window.id)"
|
@close="windowManager.closeWindow(window.id)"
|
||||||
@minimize="windowManager.minimizeWindow(window.id)"
|
@minimize="windowManager.minimizeWindow(window.id)"
|
||||||
|
|||||||
@ -4,10 +4,14 @@
|
|||||||
:style="windowStyle"
|
:style="windowStyle"
|
||||||
:class="[
|
:class="[
|
||||||
'absolute bg-default/80 backdrop-blur-xl rounded-lg shadow-xl overflow-hidden isolate',
|
'absolute bg-default/80 backdrop-blur-xl rounded-lg shadow-xl overflow-hidden isolate',
|
||||||
'border border-gray-200 dark:border-gray-700 transition-all ease-out duration-600 ',
|
'transition-all ease-out duration-600',
|
||||||
'flex flex-col @container',
|
'flex flex-col @container',
|
||||||
{ 'select-none': isResizingOrDragging },
|
{ 'select-none': isResizingOrDragging },
|
||||||
isActive ? 'z-20' : 'z-10',
|
isActive ? 'z-20' : 'z-10',
|
||||||
|
// Border colors based on warning level
|
||||||
|
warningLevel === 'warning' ? 'border-2 border-warning-500' :
|
||||||
|
warningLevel === 'danger' ? 'border-2 border-danger-500' :
|
||||||
|
'border border-gray-200 dark:border-gray-700',
|
||||||
]"
|
]"
|
||||||
@mousedown="handleActivate"
|
@mousedown="handleActivate"
|
||||||
>
|
>
|
||||||
@ -86,6 +90,7 @@ const props = defineProps<{
|
|||||||
sourceHeight?: number
|
sourceHeight?: number
|
||||||
isOpening?: boolean
|
isOpening?: boolean
|
||||||
isClosing?: boolean
|
isClosing?: boolean
|
||||||
|
warningLevel?: 'warning' | 'danger' // Warning indicator (e.g., dev extension, dangerous permissions)
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
|||||||
@ -368,7 +368,8 @@ async function handleDatabaseMethodAsync(
|
|||||||
const rows = await invoke<unknown[]>('extension_sql_select', {
|
const rows = await invoke<unknown[]>('extension_sql_select', {
|
||||||
sql: params.query || '',
|
sql: params.query || '',
|
||||||
params: params.params || [],
|
params: params.params || [],
|
||||||
extensionId: extension.id,
|
publicKey: extension.publicKey,
|
||||||
|
name: extension.name,
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -379,14 +380,15 @@ async function handleDatabaseMethodAsync(
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'haextension.db.execute': {
|
case 'haextension.db.execute': {
|
||||||
await invoke<string[]>('extension_sql_execute', {
|
const rows = await invoke<unknown[]>('extension_sql_execute', {
|
||||||
sql: params.query || '',
|
sql: params.query || '',
|
||||||
params: params.params || [],
|
params: params.params || [],
|
||||||
extensionId: extension.id,
|
publicKey: extension.publicKey,
|
||||||
|
name: extension.name,
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
rows: [],
|
rows,
|
||||||
rowsAffected: 1,
|
rowsAffected: 1,
|
||||||
lastInsertId: undefined,
|
lastInsertId: undefined,
|
||||||
}
|
}
|
||||||
@ -400,7 +402,8 @@ async function handleDatabaseMethodAsync(
|
|||||||
await invoke('extension_sql_execute', {
|
await invoke('extension_sql_execute', {
|
||||||
sql: stmt,
|
sql: stmt,
|
||||||
params: [],
|
params: [],
|
||||||
extensionId: extension.id,
|
publicKey: extension.publicKey,
|
||||||
|
name: extension.name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +0,0 @@
|
|||||||
Blocking waiting for file lock on build directory
|
|
||||||
23.313630402s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex_hub_lib"}: cargo::core::compiler::fingerprint: stale: missing "/home/haex/Projekte/haex-hub/src-tauri/src/database/schemas/crdt.ts"
|
|
||||||
23.319711685s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex_hub_lib"}: cargo::core::compiler::fingerprint: fingerprint dirty for haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri)/Check { test: false }/TargetInner { ..: lib_target("haex_hub_lib", ["staticlib", "cdylib", "rlib"], "/home/haex/Projekte/haex-hub/src-tauri/src/lib.rs", Edition2021) }
|
|
||||||
23.319734303s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex_hub_lib"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleDepFingerprint { name: "build_script_build" })
|
|
||||||
23.322781234s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="build-script-build"}: cargo::core::compiler::fingerprint: fingerprint dirty for haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri)/RunCustomBuild/TargetInner { ..: custom_build_target("build-script-build", "/home/haex/Projekte/haex-hub/src-tauri/build.rs", Edition2021) }
|
|
||||||
23.322837026s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="build-script-build"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleItem(MissingFile("/home/haex/Projekte/haex-hub/src-tauri/src/database/schemas/crdt.ts")))
|
|
||||||
23.335082427s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex_hub_lib"}: cargo::core::compiler::fingerprint: fingerprint dirty for haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri)/Check { test: true }/TargetInner { ..: lib_target("haex_hub_lib", ["staticlib", "cdylib", "rlib"], "/home/haex/Projekte/haex-hub/src-tauri/src/lib.rs", Edition2021) }
|
|
||||||
23.335103454s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex_hub_lib"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleDepFingerprint { name: "build_script_build" })
|
|
||||||
23.336844253s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex-hub"}: cargo::core::compiler::fingerprint: fingerprint dirty for haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri)/Check { test: false }/TargetInner { name: "haex-hub", doc: true, ..: with_path("/home/haex/Projekte/haex-hub/src-tauri/src/main.rs", Edition2021) }
|
|
||||||
23.336854407s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex-hub"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleDepFingerprint { name: "haex_hub_lib" })
|
|
||||||
23.338162602s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex-hub"}: cargo::core::compiler::fingerprint: fingerprint dirty for haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri)/Check { test: true }/TargetInner { name: "haex-hub", doc: true, ..: with_path("/home/haex/Projekte/haex-hub/src-tauri/src/main.rs", Edition2021) }
|
|
||||||
23.338170106s INFO prepare_target{force=false package_id=haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri) target="haex-hub"}: cargo::core::compiler::fingerprint: dirty: FsStatusOutdated(StaleDepFingerprint { name: "haex_hub_lib" })
|
|
||||||
Compiling haex-hub v0.1.0 (/home/haex/Projekte/haex-hub/src-tauri)
|
|
||||||
Finished `dev` profile [unoptimized + debuginfo] target(s) in 25.44s
|
|
||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user