From 5cdecd795cc0cac87475607df875bce79b6d6075 Mon Sep 17 00:00:00 2001 From: Diego Imbert <70353967+diegoimbert@users.noreply.github.com> Date: Thu, 5 Feb 2026 15:00:15 +0100 Subject: [PATCH] fix: fix DB Manager not working with db resources with 4+ path segments (#7809) * support more than 3 path segments * Fix explore db resource not working with 4+ path segments * don't assume 3 segments * ?table= syntax impl * update parsers * more nit fixes * fix sql query * claude nit * Update SQLx metadata --------- Co-authored-by: windmill-internal-app[bot] --- ...8caf600fb28b7553988a4b1e19792d522282.json} | 4 +- ...153c43903f929ae5d62fbba12610f89c36d55.json | 2 +- ...a2d55303f5cbf63a74d9a0ae297f256e187d.json} | 4 +- .../windmill-parser-sql/src/asset_parser.rs | 89 ++++++++- .../windmill-parser/src/asset_parser.rs | 5 +- backend/windmill-api/src/assets.rs | 8 +- frontend/package-lock.json | 178 +++++------------- frontend/package.json | 2 +- .../src/lib/components/DBManagerDrawer.svelte | 1 - .../lib/components/ExploreAssetButton.svelte | 3 +- .../lib/components/assets/AssetButtons.svelte | 8 +- .../assets/AssetsDropdownButton.svelte | 8 +- .../components/assets/JobAssetsViewer.svelte | 4 +- frontend/src/lib/components/assets/lib.ts | 6 +- .../components/flows/FlowAssetsHandler.svelte | 2 +- .../graph/renderers/nodes/AssetNode.svelte | 2 +- frontend/src/lib/components/toast.ts | 3 +- 17 files changed, 167 insertions(+), 162 deletions(-) rename backend/.sqlx/{query-6c03fc7e623afcdb11b55390ac79d9dd236e694c0af5af0ebd90df940d893258.json => query-39b5ef7a5850dc3e335a5f13f9778caf600fb28b7553988a4b1e19792d522282.json} (69%) rename backend/.sqlx/{query-34f4c05b844a83627a5c61edbfe070d0a52e20deaf550185206ae854cce274be.json => query-bbf8622cfc7852a691caf3c343aea2d55303f5cbf63a74d9a0ae297f256e187d.json} (69%) diff --git a/backend/.sqlx/query-6c03fc7e623afcdb11b55390ac79d9dd236e694c0af5af0ebd90df940d893258.json b/backend/.sqlx/query-39b5ef7a5850dc3e335a5f13f9778caf600fb28b7553988a4b1e19792d522282.json similarity index 69% rename from backend/.sqlx/query-6c03fc7e623afcdb11b55390ac79d9dd236e694c0af5af0ebd90df940d893258.json rename to backend/.sqlx/query-39b5ef7a5850dc3e335a5f13f9778caf600fb28b7553988a4b1e19792d522282.json index 85af8d8bab..9a9845db8a 100644 --- a/backend/.sqlx/query-6c03fc7e623afcdb11b55390ac79d9dd236e694c0af5af0ebd90df940d893258.json +++ b/backend/.sqlx/query-39b5ef7a5850dc3e335a5f13f9778caf600fb28b7553988a4b1e19792d522282.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "WITH job_sizes AS (\n SELECT \n cj.id,\n cj.workspace_id,\n j.parent_job,\n j.created_by,\n cj.duration_ms,\n cj.status = 'success' OR cj.status = 'skipped' AS success,\n j.runnable_id AS script_hash,\n j.runnable_path AS script_path,\n j.args,\n cj.result,\n cj.deleted,\n cj.status = 'canceled' AS canceled,\n cj.canceled_by,\n cj.canceled_reason,\n j.kind AS job_kind,\n CASE WHEN j.trigger_kind = 'schedule'::job_trigger_kind THEN j.trigger END AS schedule_path,\n j.permissioned_as,\n j.flow_step_id IS NOT NULL AS is_flow_step,\n j.script_lang AS language,\n cj.status = 'skipped' AS is_skipped,\n j.permissioned_as_email AS email,\n j.visible_to_owner,\n cj.memory_peak AS mem_peak,\n j.tag,\n cj.completed_at,\n cj.started_at,\n job_logs.logs,\n job_logs.log_offset,\n job_logs.log_file_index,\n -- Estimate size in bytes based on actual data characteristics\n (36 + -- UUID\n COALESCE(LENGTH(cj.workspace_id), 0) + \n COALESCE(LENGTH(j.created_by), 0) + \n COALESCE(LENGTH(j.runnable_path), 0) + \n COALESCE(LENGTH(j.args::text), 0) + \n COALESCE(LENGTH(cj.result::text), 0) + \n COALESCE(LENGTH(job_logs.logs), 0) + \n 200) AS estimated_size_bytes -- Other fields overhead\n FROM v2_job_completed AS cj\n JOIN v2_job AS j ON cj.id = j.id\n LEFT JOIN job_logs ON cj.id = job_logs.job_id\n WHERE (cj.completed_at > $1 AND cj.completed_at < $3)\n OR cj.id = ANY($2)\n ORDER BY completed_at ASC\n LIMIT 5000\n ),\n cumulative_sizes AS (\n SELECT \n *,\n SUM(estimated_size_bytes) OVER (\n ORDER BY completed_at ASC \n ROWS UNBOUNDED PRECEDING\n ) AS cumulative_size_bytes,\n ROW_NUMBER() OVER (ORDER BY completed_at ASC) AS row_num\n FROM job_sizes\n )\n SELECT\n id AS \"id!\",\n workspace_id AS \"workspace_id!\",\n parent_job,\n created_by AS \"created_by!\",\n duration_ms AS \"duration_ms!\",\n success AS \"success!\",\n script_hash AS \"script_hash!: Option\",\n script_path,\n args AS \"args: sqlx::types::Json>>\",\n result AS \"result: sqlx::types::Json>\",\n deleted AS \"deleted!\",\n canceled AS \"canceled!\",\n canceled_by,\n canceled_reason,\n job_kind AS \"job_kind!: JobKind\",\n schedule_path,\n permissioned_as AS \"permissioned_as!\",\n is_flow_step AS \"is_flow_step!\",\n language AS \"language: ScriptLang\",\n is_skipped AS \"is_skipped!\",\n email AS \"email!\",\n visible_to_owner AS \"visible_to_owner!\",\n mem_peak,\n tag AS \"tag!\",\n completed_at AS \"created_at!\",\n started_at,\n logs,\n log_offset AS \"log_offset?\",\n log_file_index\n FROM cumulative_sizes\n WHERE cumulative_size_bytes <= $4 OR row_num = 1\n ORDER BY completed_at ASC", + "query": "WITH job_sizes AS (\n SELECT \n cj.id,\n cj.workspace_id,\n j.parent_job,\n j.created_by,\n cj.duration_ms,\n cj.status = 'success' OR cj.status = 'skipped' AS success,\n j.runnable_id AS script_hash,\n j.runnable_path AS script_path,\n j.args,\n cj.result,\n cj.deleted,\n cj.status = 'canceled' AS canceled,\n cj.canceled_by,\n cj.canceled_reason,\n j.kind AS job_kind,\n CASE WHEN j.trigger_kind = 'schedule'::job_trigger_kind THEN j.trigger END AS schedule_path,\n j.permissioned_as,\n j.flow_step_id IS NOT NULL AS is_flow_step,\n j.script_lang AS language,\n cj.status = 'skipped' AS is_skipped,\n j.permissioned_as_email AS email,\n j.visible_to_owner,\n cj.memory_peak AS mem_peak,\n j.tag,\n cj.completed_at,\n cj.started_at,\n job_logs.logs,\n job_logs.log_offset,\n job_logs.log_file_index,\n -- Estimate size in bytes based on actual data characteristics\n (36 + -- UUID\n COALESCE(LENGTH(cj.workspace_id), 0) + \n COALESCE(LENGTH(j.created_by), 0) + \n COALESCE(LENGTH(j.runnable_path), 0) + \n COALESCE(pg_column_size(j.args), 0) +\n COALESCE(pg_column_size(cj.result), 0) + \n COALESCE(LENGTH(job_logs.logs), 0) + \n 200) AS estimated_size_bytes -- Other fields overhead\n FROM v2_job_completed AS cj\n JOIN v2_job AS j ON cj.id = j.id\n LEFT JOIN job_logs ON cj.id = job_logs.job_id\n WHERE (cj.completed_at > $1 AND cj.completed_at < $3)\n OR cj.id = ANY($2)\n ORDER BY completed_at ASC\n LIMIT 5000\n ),\n cumulative_sizes AS (\n SELECT \n *,\n SUM(estimated_size_bytes) OVER (\n ORDER BY completed_at ASC \n ROWS UNBOUNDED PRECEDING\n ) AS cumulative_size_bytes,\n ROW_NUMBER() OVER (ORDER BY completed_at ASC) AS row_num\n FROM job_sizes\n )\n SELECT\n id AS \"id!\",\n workspace_id AS \"workspace_id!\",\n parent_job,\n created_by AS \"created_by!\",\n duration_ms AS \"duration_ms!\",\n success AS \"success!\",\n script_hash AS \"script_hash!: Option\",\n script_path,\n args AS \"args: sqlx::types::Json>>\",\n result AS \"result: sqlx::types::Json>\",\n deleted AS \"deleted!\",\n canceled AS \"canceled!\",\n canceled_by,\n canceled_reason,\n job_kind AS \"job_kind!: JobKind\",\n schedule_path,\n permissioned_as AS \"permissioned_as!\",\n is_flow_step AS \"is_flow_step!\",\n language AS \"language: ScriptLang\",\n is_skipped AS \"is_skipped!\",\n email AS \"email!\",\n visible_to_owner AS \"visible_to_owner!\",\n mem_peak,\n tag AS \"tag!\",\n completed_at AS \"created_at!\",\n started_at,\n logs,\n log_offset AS \"log_offset?\",\n log_file_index\n FROM cumulative_sizes\n WHERE cumulative_size_bytes <= $4 OR row_num = 1\n ORDER BY completed_at ASC", "describe": { "columns": [ { @@ -250,5 +250,5 @@ true ] }, - "hash": "6c03fc7e623afcdb11b55390ac79d9dd236e694c0af5af0ebd90df940d893258" + "hash": "39b5ef7a5850dc3e335a5f13f9778caf600fb28b7553988a4b1e19792d522282" } diff --git a/backend/.sqlx/query-5a219a2532517869578c4504ff3153c43903f929ae5d62fbba12610f89c36d55.json b/backend/.sqlx/query-5a219a2532517869578c4504ff3153c43903f929ae5d62fbba12610f89c36d55.json index 36ddb8ab9f..713ccb9dd3 100644 --- a/backend/.sqlx/query-5a219a2532517869578c4504ff3153c43903f929ae5d62fbba12610f89c36d55.json +++ b/backend/.sqlx/query-5a219a2532517869578c4504ff3153c43903f929ae5d62fbba12610f89c36d55.json @@ -15,7 +15,7 @@ ] }, "nullable": [ - true + null ] }, "hash": "5a219a2532517869578c4504ff3153c43903f929ae5d62fbba12610f89c36d55" diff --git a/backend/.sqlx/query-34f4c05b844a83627a5c61edbfe070d0a52e20deaf550185206ae854cce274be.json b/backend/.sqlx/query-bbf8622cfc7852a691caf3c343aea2d55303f5cbf63a74d9a0ae297f256e187d.json similarity index 69% rename from backend/.sqlx/query-34f4c05b844a83627a5c61edbfe070d0a52e20deaf550185206ae854cce274be.json rename to backend/.sqlx/query-bbf8622cfc7852a691caf3c343aea2d55303f5cbf63a74d9a0ae297f256e187d.json index 8b01b0af3d..643c3ffe4b 100644 --- a/backend/.sqlx/query-34f4c05b844a83627a5c61edbfe070d0a52e20deaf550185206ae854cce274be.json +++ b/backend/.sqlx/query-bbf8622cfc7852a691caf3c343aea2d55303f5cbf63a74d9a0ae297f256e187d.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "WITH job_sizes AS (\n SELECT \n cj.id,\n cj.workspace_id,\n j.parent_job,\n j.created_by,\n cj.duration_ms,\n cj.status = 'success' OR cj.status = 'skipped' AS success,\n j.runnable_id AS script_hash,\n j.runnable_path AS script_path,\n j.args,\n cj.completed_at,\n cj.result,\n cj.deleted,\n cj.status = 'canceled' AS canceled,\n cj.canceled_by,\n cj.canceled_reason,\n j.kind AS job_kind,\n CASE WHEN j.trigger_kind = 'schedule'::job_trigger_kind THEN j.trigger END AS schedule_path,\n j.permissioned_as,\n j.flow_step_id IS NOT NULL AS is_flow_step,\n j.script_lang AS language,\n cj.status = 'skipped' AS is_skipped,\n j.permissioned_as_email AS email,\n j.visible_to_owner,\n cj.memory_peak AS mem_peak,\n j.tag,\n cj.started_at,\n job_logs.logs,\n job_logs.log_offset,\n job_logs.log_file_index,\n -- Estimate size in bytes based on actual data characteristics\n (36 + -- UUID\n COALESCE(LENGTH(cj.workspace_id), 0) + \n COALESCE(LENGTH(j.created_by), 0) + \n COALESCE(LENGTH(j.runnable_path), 0) + \n COALESCE(LENGTH(j.args::text), 0) + \n COALESCE(LENGTH(cj.result::text), 0) + \n COALESCE(LENGTH(job_logs.logs), 0) + \n 200) AS estimated_size_bytes -- Other fields overhead\n FROM v2_job_completed AS cj\n JOIN v2_job AS j ON cj.id = j.id\n LEFT JOIN job_logs ON cj.id = job_logs.job_id\n WHERE cj.completed_at < $1\n ORDER BY completed_at ASC\n LIMIT 5000\n ),\n cumulative_sizes AS (\n SELECT \n *,\n SUM(estimated_size_bytes) OVER (\n ORDER BY completed_at ASC \n ROWS UNBOUNDED PRECEDING\n ) AS cumulative_size_bytes,\n ROW_NUMBER() OVER (ORDER BY completed_at ASC) AS row_num\n FROM job_sizes\n )\n SELECT\n id AS \"id!\",\n workspace_id AS \"workspace_id!\",\n parent_job,\n created_by AS \"created_by!\",\n duration_ms AS \"duration_ms!\",\n success AS \"success!\",\n script_hash AS \"script_hash!: Option\",\n script_path,\n args AS \"args: sqlx::types::Json>>\",\n result AS \"result: sqlx::types::Json>\",\n deleted AS \"deleted!\",\n canceled AS \"canceled!\",\n canceled_by,\n canceled_reason,\n job_kind AS \"job_kind!: JobKind\",\n schedule_path,\n permissioned_as AS \"permissioned_as!\",\n is_flow_step AS \"is_flow_step!\",\n language AS \"language: ScriptLang\",\n is_skipped AS \"is_skipped!\",\n email AS \"email!\",\n visible_to_owner AS \"visible_to_owner!\",\n mem_peak,\n tag AS \"tag!\",\n completed_at AS \"created_at!\",\n started_at,\n logs,\n log_offset AS \"log_offset?\",\n log_file_index\n FROM cumulative_sizes\n WHERE cumulative_size_bytes <= $2 OR row_num = 1\n ORDER BY completed_at ASC", + "query": "WITH job_sizes AS (\n SELECT \n cj.id,\n cj.workspace_id,\n j.parent_job,\n j.created_by,\n cj.duration_ms,\n cj.status = 'success' OR cj.status = 'skipped' AS success,\n j.runnable_id AS script_hash,\n j.runnable_path AS script_path,\n j.args,\n cj.completed_at,\n cj.result,\n cj.deleted,\n cj.status = 'canceled' AS canceled,\n cj.canceled_by,\n cj.canceled_reason,\n j.kind AS job_kind,\n CASE WHEN j.trigger_kind = 'schedule'::job_trigger_kind THEN j.trigger END AS schedule_path,\n j.permissioned_as,\n j.flow_step_id IS NOT NULL AS is_flow_step,\n j.script_lang AS language,\n cj.status = 'skipped' AS is_skipped,\n j.permissioned_as_email AS email,\n j.visible_to_owner,\n cj.memory_peak AS mem_peak,\n j.tag,\n cj.started_at,\n job_logs.logs,\n job_logs.log_offset,\n job_logs.log_file_index,\n -- Estimate size in bytes based on actual data characteristics\n (36 + -- UUID\n COALESCE(LENGTH(cj.workspace_id), 0) + \n COALESCE(LENGTH(j.created_by), 0) + \n COALESCE(LENGTH(j.runnable_path), 0) + \n COALESCE(pg_column_size(j.args), 0) +\n COALESCE(pg_column_size(cj.result), 0) + \n COALESCE(LENGTH(job_logs.logs), 0) + \n 200) AS estimated_size_bytes -- Other fields overhead\n FROM v2_job_completed AS cj\n JOIN v2_job AS j ON cj.id = j.id\n LEFT JOIN job_logs ON cj.id = job_logs.job_id\n WHERE cj.completed_at < $1\n ORDER BY completed_at ASC\n LIMIT 5000\n ),\n cumulative_sizes AS (\n SELECT \n *,\n SUM(estimated_size_bytes) OVER (\n ORDER BY completed_at ASC \n ROWS UNBOUNDED PRECEDING\n ) AS cumulative_size_bytes,\n ROW_NUMBER() OVER (ORDER BY completed_at ASC) AS row_num\n FROM job_sizes\n )\n SELECT\n id AS \"id!\",\n workspace_id AS \"workspace_id!\",\n parent_job,\n created_by AS \"created_by!\",\n duration_ms AS \"duration_ms!\",\n success AS \"success!\",\n script_hash AS \"script_hash!: Option\",\n script_path,\n args AS \"args: sqlx::types::Json>>\",\n result AS \"result: sqlx::types::Json>\",\n deleted AS \"deleted!\",\n canceled AS \"canceled!\",\n canceled_by,\n canceled_reason,\n job_kind AS \"job_kind!: JobKind\",\n schedule_path,\n permissioned_as AS \"permissioned_as!\",\n is_flow_step AS \"is_flow_step!\",\n language AS \"language: ScriptLang\",\n is_skipped AS \"is_skipped!\",\n email AS \"email!\",\n visible_to_owner AS \"visible_to_owner!\",\n mem_peak,\n tag AS \"tag!\",\n completed_at AS \"created_at!\",\n started_at,\n logs,\n log_offset AS \"log_offset?\",\n log_file_index\n FROM cumulative_sizes\n WHERE cumulative_size_bytes <= $2 OR row_num = 1\n ORDER BY completed_at ASC", "describe": { "columns": [ { @@ -248,5 +248,5 @@ true ] }, - "hash": "34f4c05b844a83627a5c61edbfe070d0a52e20deaf550185206ae854cce274be" + "hash": "bbf8622cfc7852a691caf3c343aea2d55303f5cbf63a74d9a0ae297f256e187d" } diff --git a/backend/parsers/windmill-parser-sql/src/asset_parser.rs b/backend/parsers/windmill-parser-sql/src/asset_parser.rs index 51b90b379a..9db4e8a0d0 100644 --- a/backend/parsers/windmill-parser-sql/src/asset_parser.rs +++ b/backend/parsers/windmill-parser-sql/src/asset_parser.rs @@ -87,7 +87,14 @@ impl AssetCollector { .map(|id| id.as_ident().map(|id| id.value.clone())) .collect::>>()? .join("."); - let path = format!("{}/{}", path, specific_table); + + // For Resource assets, use ?table= query parameter syntax + // For Ducklake and DataTable, maintain /table syntax + let path = if *kind == AssetKind::Resource { + format!("{}?table={}", path, specific_table) + } else { + format!("{}/{}", path, specific_table) + }; return Some(ParseAssetsResult { kind: *kind, access_type, path, columns: None }); } } @@ -104,7 +111,14 @@ impl AssetCollector { .map(|id| id.as_ident().map(|id| id.value.clone())) .collect::>>()? .join("."); - format!("{}/{}", path, specific_table) + + // For Resource assets, use ?table= query parameter syntax + // For Ducklake and DataTable, maintain /table syntax + if *kind == AssetKind::Resource { + format!("{}?table={}", path, specific_table) + } else { + format!("{}/{}", path, specific_table) + } } else { path.clone() }; @@ -845,7 +859,7 @@ mod tests { s.map_err(|e| e.to_string()), Ok(vec![ParseAssetsResult { kind: AssetKind::Resource, - path: "u/user/pg_resource/table1".to_string(), + path: "u/user/pg_resource?table=table1".to_string(), access_type: Some(R), columns: None },]) @@ -870,6 +884,75 @@ mod tests { ); } + #[test] + fn test_sql_asset_parser_resource_vs_ducklake_syntax() { + // Test that Resource uses ?table= while Ducklake uses /table + let input_resource = r#" + ATTACH 'res://u/user/pg_resource' AS db (TYPE postgres); + SELECT * FROM db.users; + "#; + let s = parse_assets(input_resource).map(|s| s.assets); + assert_eq!( + s.map_err(|e| e.to_string()), + Ok(vec![ParseAssetsResult { + kind: AssetKind::Resource, + path: "u/user/pg_resource?table=users".to_string(), + access_type: Some(R), + columns: None + },]) + ); + + let input_ducklake = r#" + ATTACH 'ducklake://my_lake' AS dl; + SELECT * FROM dl.users; + "#; + let s = parse_assets(input_ducklake).map(|s| s.assets); + assert_eq!( + s.map_err(|e| e.to_string()), + Ok(vec![ParseAssetsResult { + kind: AssetKind::Ducklake, + path: "my_lake/users".to_string(), + access_type: Some(R), + columns: None + },]) + ); + + let input_datatable = r#" + ATTACH 'datatable://dt1' AS dt; + SELECT * FROM dt.users; + "#; + let s = parse_assets(input_datatable).map(|s| s.assets); + assert_eq!( + s.map_err(|e| e.to_string()), + Ok(vec![ParseAssetsResult { + kind: AssetKind::DataTable, + path: "dt1/users".to_string(), + access_type: Some(R), + columns: None + },]) + ); + } + + #[test] + fn test_sql_asset_parser_resource_with_long_path() { + // Test that Resource works with paths longer than 3 components + let input = r#" + ATTACH 'res://u/diego/a/b/c/my_postgres_resource' AS db (TYPE postgres); + USE db; + SELECT * FROM my_table; + "#; + let s = parse_assets(input).map(|s| s.assets); + assert_eq!( + s.map_err(|e| e.to_string()), + Ok(vec![ParseAssetsResult { + kind: AssetKind::Resource, + path: "u/diego/a/b/c/my_postgres_resource?table=my_table".to_string(), + access_type: Some(R), + columns: None + },]) + ); + } + #[test] fn test_sql_asset_parser_table_with_schema() { let input = r#" diff --git a/backend/parsers/windmill-parser/src/asset_parser.rs b/backend/parsers/windmill-parser/src/asset_parser.rs index 4f88fe17c1..2463995606 100644 --- a/backend/parsers/windmill-parser/src/asset_parser.rs +++ b/backend/parsers/windmill-parser/src/asset_parser.rs @@ -114,13 +114,14 @@ fn merge_access_types(a: AssetUsageAccessType, b: AssetUsageAccessType) -> Asset // But never used it. In that case we don't know which table is being used, // but we still want to add the main datatable as an asset with unknown access type. // -// This function takes care of the fact that assets can be suffixed (e.g. "main/users") +// This function takes care of the fact that assets can be suffixed (e.g. "main/users" or "u/user/resource?table=table1") pub fn asset_was_used(assets: &Vec, (kind, path): (AssetKind, &String)) -> bool { assets.iter().any(|a| { let a_path = a.path.as_str(); + // Check for /table suffix (Ducklake, DataTable) or ?table= suffix (Resource) let has_same_path_base = a_path .strip_prefix(path) - .map(|p| p.starts_with('/')) + .map(|p| p.starts_with('/') || p.starts_with('?')) .unwrap_or(false); (has_same_path_base || a_path == path) && a.kind == kind }) diff --git a/backend/windmill-api/src/assets.rs b/backend/windmill-api/src/assets.rs index 6a53c90ebd..8e8afc7036 100644 --- a/backend/windmill-api/src/assets.rs +++ b/backend/windmill-api/src/assets.rs @@ -184,7 +184,13 @@ async fn list_assets( FROM asset INNER JOIN asset_summary ON asset.path = asset_summary.path AND asset.kind = asset_summary.kind LEFT JOIN resource ON asset.kind = 'resource' - AND array_to_string((string_to_array(asset.path, '/'))[1:3], '/') = resource.path + AND ( + -- Extract base path before '?' for ?table= syntax + CASE + WHEN asset.path LIKE '%?%' THEN split_part(asset.path, '?', 1) + ELSE asset.path + END + ) = resource.path AND resource.workspace_id = $1 LEFT JOIN v2_job job ON asset.usage_kind = 'job' AND asset.usage_path = job.id::text diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b39bc81ea6..929d9ea62b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -80,7 +80,7 @@ "windmill-parser-wasm-nu": "1.510.1", "windmill-parser-wasm-php": "1.574.1", "windmill-parser-wasm-py": "1.623.1", - "windmill-parser-wasm-regex": "1.623.1", + "windmill-parser-wasm-regex": "1.625.0", "windmill-parser-wasm-ruby": "1.526.1", "windmill-parser-wasm-rust": "1.558.1", "windmill-parser-wasm-ts": "1.623.1", @@ -259,7 +259,6 @@ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", @@ -275,7 +274,6 @@ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6.9.0" } @@ -821,7 +819,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": "^14 || ^16 || >=18" }, @@ -1331,6 +1328,7 @@ "integrity": "sha512-Jer+M7DgIwT5IHfTayb4Iw/fkkxWNmC/mqn/nMh9JrbPbkxmyabfLQnhJ+JDn5HK77f84j34lubO3iqFtYAfMg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@floating-ui/core": "^1.3.1", "@floating-ui/dom": "^1.4.5", @@ -2106,6 +2104,7 @@ "integrity": "sha512-Vp3zX/qlwerQmHMP6x0Ry1oY7eKKRcOWGc2P59srOp4zcqyn+etJyQpELgOi4+ZSUgteX8Y387NuwruLgGXLUQ==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", @@ -2183,6 +2182,7 @@ "integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "debug": "^4.4.1", @@ -2709,8 +2709,7 @@ "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/ms": { "version": "2.1.0", @@ -2723,8 +2722,7 @@ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/semver": { "version": "7.7.1", @@ -2794,6 +2792,7 @@ "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", @@ -2962,7 +2961,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@vitest/mocker": "4.0.15", "@vitest/utils": "4.0.15", @@ -2987,7 +2985,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@vitest/browser": "4.0.15", "@vitest/mocker": "4.0.15", @@ -3013,7 +3010,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@vitest/spy": "4.0.15", "estree-walker": "^3.0.3", @@ -3042,7 +3038,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@vitest/spy": "4.0.15", "estree-walker": "^3.0.3", @@ -3274,6 +3269,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3327,6 +3323,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -3472,7 +3469,6 @@ "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -3500,7 +3496,6 @@ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -3593,8 +3588,7 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", @@ -3721,6 +3715,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -3918,7 +3913,6 @@ "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "camelcase": "^6.3.0", "map-obj": "^4.1.0", @@ -3938,7 +3932,6 @@ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -3952,7 +3945,6 @@ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -3966,7 +3958,6 @@ "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", "dev": true, "license": "(MIT OR CC0-1.0)", - "peer": true, "engines": { "node": ">=10" }, @@ -4075,6 +4066,7 @@ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz", "integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==", "license": "MIT", + "peer": true, "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -4321,7 +4313,6 @@ "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -4386,7 +4377,6 @@ "integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12 || >=16" } @@ -4652,6 +4642,7 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", + "peer": true, "engines": { "node": ">=12" } @@ -4705,6 +4696,7 @@ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.21.0" }, @@ -4739,7 +4731,6 @@ "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -4753,7 +4744,6 @@ "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "decamelize": "^1.1.0", "map-obj": "^1.0.0" @@ -4771,7 +4761,6 @@ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4782,7 +4771,6 @@ "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -5268,7 +5256,6 @@ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "is-arrayish": "^0.2.1" } @@ -5356,6 +5343,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -5902,7 +5890,6 @@ "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 4.9.1" } @@ -6388,7 +6375,6 @@ "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "global-prefix": "^3.0.0" }, @@ -6402,7 +6388,6 @@ "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ini": "^1.3.5", "kind-of": "^6.0.2", @@ -6418,7 +6403,6 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "isexe": "^2.0.0" }, @@ -6468,8 +6452,7 @@ "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/gopd": { "version": "1.2.0", @@ -6546,7 +6529,6 @@ "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -6768,7 +6750,6 @@ "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -6782,7 +6763,6 @@ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -6795,8 +6775,7 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/html-tags": { "version": "3.3.1", @@ -6804,7 +6783,6 @@ "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" }, @@ -6888,7 +6866,6 @@ "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -6909,7 +6886,6 @@ "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6980,8 +6956,7 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/is-binary-path": { "version": "2.1.0", @@ -7086,7 +7061,6 @@ "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -7097,7 +7071,6 @@ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -7202,8 +7175,7 @@ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", @@ -7239,8 +7211,7 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/json-refs": { "version": "3.0.15", @@ -7407,7 +7378,6 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -8001,8 +7971,7 @@ "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.uniq": { "version": "4.5.0", @@ -8070,7 +8039,6 @@ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" }, @@ -8121,7 +8089,6 @@ "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", "dev": true, "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -8362,7 +8329,6 @@ "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/minimist": "^1.2.2", "camelcase-keys": "^7.0.0", @@ -8390,7 +8356,6 @@ "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", "dev": true, "license": "(MIT OR CC0-1.0)", - "peer": true, "engines": { "node": ">=10" }, @@ -9084,7 +9049,6 @@ "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "arrify": "^1.0.1", "is-plain-obj": "^1.1.0", @@ -9163,6 +9127,7 @@ "resolved": "https://registry.npmjs.org/@codingame/monaco-vscode-editor-api/-/monaco-vscode-editor-api-25.0.0.tgz", "integrity": "sha512-uiY06RTWFo2WZdh6OybkLlDhuG+8LlkjUDpr9/wW55uucqHo4X8fx4XKEtD98cscC+6FKQkbG2yyUiOJ/npHOw==", "license": "MIT", + "peer": true, "dependencies": { "@codingame/monaco-vscode-api": "25.0.0" } @@ -9399,7 +9364,6 @@ "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "hosted-git-info": "^4.0.1", "is-core-module": "^2.5.0", @@ -9745,7 +9709,6 @@ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -9957,7 +9920,6 @@ "dev": true, "license": "ISC", "optional": true, - "peer": true, "dependencies": { "pngjs": "^7.0.0" }, @@ -10047,7 +10009,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">=14.19.0" } @@ -10072,6 +10033,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -10260,6 +10222,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "lilconfig": "^3.0.0", "yaml": "^2.3.4" @@ -10649,8 +10612,7 @@ "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/postcss-safe-parser": { "version": "6.0.0", @@ -10826,6 +10788,7 @@ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -11136,7 +11099,6 @@ "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^3.0.2", @@ -11156,7 +11118,6 @@ "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "find-up": "^5.0.0", "read-pkg": "^6.0.0", @@ -11175,7 +11136,6 @@ "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", "dev": true, "license": "(MIT OR CC0-1.0)", - "peer": true, "engines": { "node": ">=10" }, @@ -11189,7 +11149,6 @@ "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", "dev": true, "license": "(MIT OR CC0-1.0)", - "peer": true, "engines": { "node": ">=10" }, @@ -11232,7 +11191,6 @@ "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "indent-string": "^5.0.0", "strip-indent": "^4.0.0" @@ -11875,7 +11833,6 @@ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -11952,7 +11909,6 @@ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -11963,8 +11919,7 @@ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true, - "license": "CC-BY-3.0", - "peer": true + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { "version": "3.0.1", @@ -11972,7 +11927,6 @@ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -11983,8 +11937,7 @@ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", "dev": true, - "license": "CC0-1.0", - "peer": true + "license": "CC0-1.0" }, "node_modules/sprintf-js": { "version": "1.0.3", @@ -12078,7 +12031,6 @@ "integrity": "sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -12104,8 +12056,7 @@ "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/style-to-object": { "version": "0.4.4", @@ -12154,7 +12105,6 @@ "integrity": "sha512-78O4c6IswZ9TzpcIiQJIN49K3qNoXTM8zEJzhaTE/xRTCZswaovSEVIa/uwbOltZrk16X4jAxjaOhzz/hTm1Kw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@csstools/css-parser-algorithms": "^2.3.1", "@csstools/css-tokenizer": "^2.2.0", @@ -12237,7 +12187,6 @@ } ], "license": "MIT-0", - "peer": true, "engines": { "node": "^14 || ^16 || >=18" }, @@ -12251,7 +12200,6 @@ "integrity": "sha512-TfW7/1iI4Cy7Y8L6iqNdZQVvdXn0f8B4QcIXmkIbtTIe/Okm/nSlHb4IwGzRVOd3WfSieCgvf5cMzEfySAIl0g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "flat-cache": "^3.2.0" }, @@ -12264,8 +12212,7 @@ "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.29.0.tgz", "integrity": "sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/stylelint/node_modules/postcss-selector-parser": { "version": "6.1.2", @@ -12288,7 +12235,6 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -12423,7 +12369,6 @@ "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" @@ -12453,6 +12398,7 @@ "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.39.12.tgz", "integrity": "sha512-CEzwxFuEycokU8K8CE/OuwVbmei+ivu2HvBGYIdASfMa1hCRSNr4RRkzNSvbAvu6h+BOig2CsZTAEY+WKvwZpA==", "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", @@ -12548,21 +12494,6 @@ } } }, - "node_modules/svelte-check/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/svelte-eslint-parser": { "version": "0.43.0", "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.43.0.tgz", @@ -12750,8 +12681,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/svgo": { "version": "3.3.2", @@ -12802,7 +12732,6 @@ "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -12830,6 +12759,7 @@ "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -13072,6 +13002,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "devOptional": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -13134,7 +13065,6 @@ "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -13233,6 +13163,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -13446,7 +13377,6 @@ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -13501,6 +13431,7 @@ "integrity": "sha512-5hI5NCJwKBGtzWtdKB3c2fOEpI77Iaa0z4mSzZPU1cJ/OqrGbFafm90edVCd7T9Snz+Sh09TMAv4EQqyVLzuEg==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "@oxc-project/runtime": "0.101.0", "fdir": "^6.5.0", @@ -13613,6 +13544,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "devOptional": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -13626,6 +13558,7 @@ "integrity": "sha512-n1RxDp8UJm6N0IbJLQo+yzLZ2sQCDyl1o0LeugbPWf8+8Fttp29GghsQBjYJVmWq3gBFfe9Hs1spR44vovn2wA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vitest/expect": "4.0.15", "@vitest/mocker": "4.0.15", @@ -14254,6 +14187,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -14277,6 +14211,7 @@ "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -14608,9 +14543,9 @@ "integrity": "sha512-lFBlZg6hvhHzsU5oPJq0478UyMTZ9UKVd8Hc8ggmxPIHZaJBeJ+56NR75hmGwg0VJcRff8ed+zEm1PgmjVhD+w==" }, "node_modules/windmill-parser-wasm-regex": { - "version": "1.623.1", - "resolved": "https://registry.npmjs.org/windmill-parser-wasm-regex/-/windmill-parser-wasm-regex-1.623.1.tgz", - "integrity": "sha512-rW3pl4ysIXmVAmwxSTKhR2sUfScXKfTqxrUebDg0ZNcUzY97S8mNRdQGZfaQ1NWhWPRQNXfL/z/yaUOQh5ConQ==" + "version": "1.625.0", + "resolved": "https://registry.npmjs.org/windmill-parser-wasm-regex/-/windmill-parser-wasm-regex-1.625.0.tgz", + "integrity": "sha512-xXzr0O2+U4IaQW8Y+SlbU2wEN5lyZhb+ZjO0LouWVlbQkj/RVeQkQ1M7tZr5LlmvGwXbFmBjct/3IjVR8c3Qwg==" }, "node_modules/windmill-parser-wasm-ruby": { "version": "1.526.1", @@ -14776,7 +14711,6 @@ "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^4.0.1" @@ -14785,29 +14719,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/ws": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", - "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/xml-utils": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/xml-utils/-/xml-utils-1.10.2.tgz", @@ -14995,7 +14906,6 @@ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, "license": "ISC", - "peer": true, "engines": { "node": ">=10" } @@ -15015,6 +14925,7 @@ "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.27.tgz", "integrity": "sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw==", "license": "MIT", + "peer": true, "dependencies": { "lib0": "^0.2.99" }, @@ -15050,6 +14961,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/frontend/package.json b/frontend/package.json index c7d8e1ac36..a1b94525bf 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -150,7 +150,7 @@ "windmill-parser-wasm-nu": "1.510.1", "windmill-parser-wasm-php": "1.574.1", "windmill-parser-wasm-py": "1.623.1", - "windmill-parser-wasm-regex": "1.623.1", + "windmill-parser-wasm-regex": "1.625.0", "windmill-parser-wasm-ruby": "1.526.1", "windmill-parser-wasm-rust": "1.558.1", "windmill-parser-wasm-ts": "1.623.1", diff --git a/frontend/src/lib/components/DBManagerDrawer.svelte b/frontend/src/lib/components/DBManagerDrawer.svelte index b899019826..c5986e18a4 100644 --- a/frontend/src/lib/components/DBManagerDrawer.svelte +++ b/frontend/src/lib/components/DBManagerDrawer.svelte @@ -57,7 +57,6 @@ ) export function openDrawer(nInput: DbInput) { - console.log('Opening DB Manager with input:', nInput) input = nInput if (isDatatableInput) { datatables.refetch() diff --git a/frontend/src/lib/components/ExploreAssetButton.svelte b/frontend/src/lib/components/ExploreAssetButton.svelte index d2f886fa6d..ba623b4e4e 100644 --- a/frontend/src/lib/components/ExploreAssetButton.svelte +++ b/frontend/src/lib/components/ExploreAssetButton.svelte @@ -58,8 +58,7 @@ {btnClasses} on:click={async () => { if (asset.kind === 'resource' && isDbType(_resourceMetadata?.resource_type)) { - let resourcePath = asset.path.split('/').slice(0, 3).join('/') - let specificTable = asset.path.split('/')[3] as string | undefined + let [resourcePath, specificTable] = asset.path.split('?table=') dbManagerDrawer?.openDrawer({ type: 'database', resourceType: _resourceMetadata.resource_type, diff --git a/frontend/src/lib/components/assets/AssetButtons.svelte b/frontend/src/lib/components/assets/AssetButtons.svelte index f322abed8a..976cfa6dc3 100644 --- a/frontend/src/lib/components/assets/AssetButtons.svelte +++ b/frontend/src/lib/components/assets/AssetButtons.svelte @@ -29,10 +29,8 @@ onClick }: Props = $props() - let resourceDataCacheValue = $derived.by(() => { - let truncatedPath = asset.path.split('/').slice(0, 3).join('/') - return resourceDataCache[truncatedPath] - }) + let truncatedPath = asset.path.split('?table=')[0] + let resourceDataCacheValue = $derived(resourceDataCache[truncatedPath])
@@ -42,7 +40,7 @@ variant="default" unifiedSize="md" iconOnly - on:click={() => (resourceEditorDrawer?.initEdit(asset.path), onClick?.())} + on:click={() => (resourceEditorDrawer?.initEdit(truncatedPath), onClick?.())} /> {/if} {#if (asset.kind === 'resource' && resourceDataCacheValue === undefined) || ducklakeNotFound || datatableNotFound} diff --git a/frontend/src/lib/components/assets/AssetsDropdownButton.svelte b/frontend/src/lib/components/assets/AssetsDropdownButton.svelte index 17d6546d1d..1e1e1871ae 100644 --- a/frontend/src/lib/components/assets/AssetsDropdownButton.svelte +++ b/frontend/src/lib/components/assets/AssetsDropdownButton.svelte @@ -84,7 +84,7 @@ for (const asset of assets) { if (asset.kind == 'resource') { - let truncatedPath = asset.path.split('/').slice(0, 3).join('/') + let truncatedPath = asset.path.split('?table=')[0] if (truncatedPath in resourceDataCache) continue resourceDataCache[truncatedPath] = undefined // avoid fetching multiple times because of async ResourceService.getResource({ path: truncatedPath, workspace: $workspaceStore! }) @@ -195,7 +195,11 @@ formatAssetKind({ ...asset, ...(asset.kind === 'resource' - ? { metadata: { resource_type: resourceDataCache[asset.path] } } + ? { + metadata: { + resource_type: resourceDataCache[asset.path.split('?table=')[0]] + } + } : {}) })} diff --git a/frontend/src/lib/components/assets/JobAssetsViewer.svelte b/frontend/src/lib/components/assets/JobAssetsViewer.svelte index 28e68e1068..2eccf66d51 100644 --- a/frontend/src/lib/components/assets/JobAssetsViewer.svelte +++ b/frontend/src/lib/components/assets/JobAssetsViewer.svelte @@ -53,7 +53,7 @@ $effect(() => { for (const asset of assets.value ?? []) { if (asset.kind == 'resource') { - let truncatedPath = asset.path.split('/').slice(0, 3).join('/') + let truncatedPath = asset.path.split('?table=')[0] if (truncatedPath in resourceDataCache) continue resourceDataCache[truncatedPath] = undefined // avoid fetching multiple times because of async ResourceService.getResource({ path: truncatedPath, workspace: $workspaceStore! }) @@ -78,7 +78,7 @@ {formatAssetKind({ ...asset, ...(asset.kind === 'resource' - ? { metadata: { resource_type: resourceDataCache[asset.path] } } + ? { metadata: { resource_type: resourceDataCache[asset.path.split('?table=')[0]] } } : {}) })} diff --git a/frontend/src/lib/components/assets/lib.ts b/frontend/src/lib/components/assets/lib.ts index 2475e2b126..c991ecc46b 100644 --- a/frontend/src/lib/components/assets/lib.ts +++ b/frontend/src/lib/components/assets/lib.ts @@ -31,7 +31,11 @@ export function formatAsset(asset: Asset): string { } export function formatShortAssetPath(asset: Asset): string { - return asset.path.split('/').pop() || asset.path + if (asset.kind === 'datatable' && asset.path === 'main') return 'Main data table' + if (asset.kind === 'ducklake' && asset.path === 'main') return 'Main ducklake' + const s = asset.path.split('/').pop() || asset.path + if (s.includes('?table=')) return s.split('?table=')[1] + return s } export function getAssetUsagePageUri(usage: AssetUsage) { diff --git a/frontend/src/lib/components/flows/FlowAssetsHandler.svelte b/frontend/src/lib/components/flows/FlowAssetsHandler.svelte index 7d55ed5cfa..5926d8461b 100644 --- a/frontend/src/lib/components/flows/FlowAssetsHandler.svelte +++ b/frontend/src/lib/components/flows/FlowAssetsHandler.svelte @@ -75,7 +75,7 @@ ) ?? [] for (const asset of assets) { if (asset.kind == 'resource') { - let truncatedPath = asset.path.split('/').slice(0, 3).join('/') + let truncatedPath = asset.path.split('?table=')[0] if (truncatedPath in resMetadataCache) continue resMetadataCache[truncatedPath] = undefined // avoid fetching multiple times because of async ResourceService.getResource({ path: truncatedPath, workspace: $workspaceStore! }) diff --git a/frontend/src/lib/components/graph/renderers/nodes/AssetNode.svelte b/frontend/src/lib/components/graph/renderers/nodes/AssetNode.svelte index 26369b7833..15efe7e98e 100644 --- a/frontend/src/lib/components/graph/renderers/nodes/AssetNode.svelte +++ b/frontend/src/lib/components/graph/renderers/nodes/AssetNode.svelte @@ -250,7 +250,7 @@ const isSelected = $derived(assetEq(flowGraphAssetsCtx?.val.selectedAsset, data.asset)) const cachedResourceMetadata = $derived.by(() => { if (data.asset.kind !== 'resource') return undefined - let truncatedPath = data.asset.path.split('/').slice(0, 3).join('/') + let truncatedPath = data.asset.path.split('?table=')[0] return flowGraphAssetsCtx?.val.resourceMetadataCache[truncatedPath] }) const usageCount = $derived(flowGraphAssetsCtx?.val.computeAssetsCount?.(data.asset)) diff --git a/frontend/src/lib/components/toast.ts b/frontend/src/lib/components/toast.ts index cf03b497be..6a68f76f26 100644 --- a/frontend/src/lib/components/toast.ts +++ b/frontend/src/lib/components/toast.ts @@ -1,5 +1,4 @@ -//regex that match path starting with u/ or f/ and with at least 2 / -const pathRegex = /\b(u|f)\/[^\/\s]+\/[^\/\s]+\b/g +const pathRegex = /\b(u|f)(\/[^\/\s]+){2,}\b/g export function processMessage(message: string | undefined): string { let msg = !message