From b3d8b847c6f92290d36130580b15fcecd684bd15 Mon Sep 17 00:00:00 2001 From: zknpr Date: Sat, 30 May 2026 22:24:50 +0200 Subject: [PATCH 1/3] refactor(ui): extract testable batch-update logic from sidebar.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reworks the closed #360/#361 (which couldn't be unit-tested as in-file helpers — sidebar.js's import chain requires a DOM). Extracts the pure value-processing logic into a DOM-free module so it can be unit-tested: - core/ui/modules/batch-update-logic.js (+ .d.ts): groupSelectedCellsByColumn, summarizeColumnValue, prepareBatchUpdates (type coercion / NULL / json_patch / skip-empty rules) - sidebar.js: updateBatchSidebar + applyBatchUpdate delegate to these (behavior unchanged); removed a now-unused escapeHtml import - tests/unit/batch-update-logic.test.ts: 13 cases covering the rules Verified: 324 unit tests pass (was 311); tsc --noEmit clean; full batch-update flow runtime-checked in the web demo (select 2 cells -> panel shows the grouped column with "(mixed values)" -> apply -> both cells update; zero console errors). Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-Authored-By: Claude Opus 4.8 (1M context) --- core/ui/modules/batch-update-logic.d.ts | 50 +++++++++++ core/ui/modules/batch-update-logic.js | 96 +++++++++++++++++++++ core/ui/modules/sidebar.js | 76 ++--------------- core/ui/viewer.html | 22 ++--- tests/unit/batch-update-logic.test.ts | 101 +++++++++++++++++++++++ website/public/sqlite-viewer/viewer.html | 24 +++--- 6 files changed, 276 insertions(+), 93 deletions(-) create mode 100644 core/ui/modules/batch-update-logic.d.ts create mode 100644 core/ui/modules/batch-update-logic.js create mode 100644 tests/unit/batch-update-logic.test.ts diff --git a/core/ui/modules/batch-update-logic.d.ts b/core/ui/modules/batch-update-logic.d.ts new file mode 100644 index 0000000..ceaa29a --- /dev/null +++ b/core/ui/modules/batch-update-logic.d.ts @@ -0,0 +1,50 @@ +/** + * Types for batch-update-logic.js (DOM-free batch-update helpers). + */ + +export interface BatchSelectedCell { + rowId: string | number; + rowIdx: number; + colIdx: number; + value: unknown; +} + +export interface BatchColumnDef { + name: string; + type?: string; +} + +/** Minimal shape of a batch-field (real element or test stand-in). */ +export interface BatchInputLike { + value: string; + dataset: { isnull?: string; ispatch?: string }; +} + +export interface BatchColumnInfo { + name: string; + type?: string; + values: Set; +} + +export interface PreparedBatchUpdate { + rowId: string | number; + column: string; + value: unknown; + originalValue: unknown; + operation: 'set' | 'json_patch'; + rowIdx: number; + colIdx: number; +} + +export function groupSelectedCellsByColumn( + selectedCells: BatchSelectedCell[], + tableColumns: BatchColumnDef[] +): Map; + +export function summarizeColumnValue(values: Iterable): string; + +export function prepareBatchUpdates( + selectedCells: BatchSelectedCell[], + inputsByCol: Map, + tableColumns: BatchColumnDef[] +): PreparedBatchUpdate[]; diff --git a/core/ui/modules/batch-update-logic.js b/core/ui/modules/batch-update-logic.js new file mode 100644 index 0000000..7c5bf0e --- /dev/null +++ b/core/ui/modules/batch-update-logic.js @@ -0,0 +1,96 @@ +/** + * Batch Update Logic (DOM-free, unit-testable) + * + * Pure helpers extracted from sidebar.js's batch-update flow so the + * value-processing rules (column grouping, value summarisation, type + * coercion, NULL/json_patch handling, skip-empty) can be unit-tested + * without a DOM. sidebar.js wires these into the actual DOM. + * + * Types live in batch-update-logic.d.ts. + */ + +/** + * Group the selected cells by column index. + * @returns Map of colIdx -> { name, type, values } where `values` is the set + * of distinct cell values currently selected in that column. + */ +export function groupSelectedCellsByColumn(selectedCells, tableColumns) { + const columns = new Map(); + for (const cell of selectedCells) { + if (!columns.has(cell.colIdx)) { + const colDef = tableColumns[cell.colIdx]; + columns.set(cell.colIdx, { + name: colDef.name, + type: colDef.type, + values: new Set() + }); + } + columns.get(cell.colIdx).values.add(cell.value); + } + return columns; +} + +/** + * Placeholder text describing a column's current selected value(s): + * '(mixed values)' when the selection spans differing values, otherwise the + * single shared value rendered as NULL / [BLOB] / its string form. + */ +export function summarizeColumnValue(values) { + const uniqueValues = Array.from(values); + if (uniqueValues.length > 1) return '(mixed values)'; + const val = uniqueValues[0]; + if (val === null) return 'NULL'; + if (val instanceof Uint8Array) return '[BLOB]'; + return String(val); +} + +/** + * Build the list of cell updates to send to the backend. + * + * `inputsByCol` maps a column index to an input-like object + * ({ value, dataset:{ isnull, ispatch } }) — in the browser these are the + * real elements; in tests they are plain stand-ins. Mirrors the + * batch form's rules: skip cells left blank (unless explicitly NULL), tag + * json_patch operations, and coerce numeric column types. + */ +export function prepareBatchUpdates(selectedCells, inputsByCol, tableColumns) { + const updates = []; + for (const cell of selectedCells) { + const input = inputsByCol.get(cell.colIdx); + if (!input) continue; + + const isNull = input.dataset.isnull === 'true'; + const isPatch = input.dataset.ispatch === 'true'; + const value = input.value; + + // Skip cells left blank unless they were explicitly set to NULL. + if (value === '' && !isNull) continue; + + const colDef = tableColumns[cell.colIdx]; + + let finalValue = value; + let operation = 'set'; + + if (isNull) { + finalValue = null; + } else if (isPatch) { + operation = 'json_patch'; + } else if (colDef.type === 'INTEGER' || colDef.type === 'REAL' || colDef.type === 'NUMERIC') { + // Coerce numeric column types when the input parses as a number. + if (!isNaN(Number(value)) && value.trim() !== '') { + finalValue = Number(value); + } + } + + updates.push({ + rowId: cell.rowId, + column: colDef.name, + value: finalValue, + originalValue: cell.value, + operation, + rowIdx: cell.rowIdx, + colIdx: cell.colIdx + }); + } + return updates; +} diff --git a/core/ui/modules/sidebar.js b/core/ui/modules/sidebar.js index 2949e35..7061237 100644 --- a/core/ui/modules/sidebar.js +++ b/core/ui/modules/sidebar.js @@ -3,12 +3,12 @@ */ import { state, persistState } from './state.js'; import { backendApi } from './api.js'; -import { escapeHtml } from './utils.js'; import { updateStatus } from './ui.js'; import { loadTableData, loadTableColumns } from './grid.js'; import { getRowDataOffset } from './data-utils.js'; import { openCreateTableModal } from './crud.js'; import { openSettingsModal } from './settings.js'; +import { groupSelectedCellsByColumn, summarizeColumnValue, prepareBatchUpdates } from './batch-update-logic.js'; export function initSidebar() { const sidebarPanel = document.getElementById('sidebarPanel'); @@ -254,36 +254,13 @@ export function updateBatchSidebar() { countBadge.textContent = cellCount; - // Analyze selected cells - Group by column - const columns = new Map(); - - for (const cell of state.selectedCells) { - if (!columns.has(cell.colIdx)) { - const colDef = state.tableColumns[cell.colIdx]; - columns.set(cell.colIdx, { - name: colDef.name, - type: colDef.type, - values: new Set() - }); - } - columns.get(cell.colIdx).values.add(cell.value); - } + // Analyze selected cells - group by column (see batch-update-logic.js) + const columns = groupSelectedCellsByColumn(state.selectedCells, state.tableColumns); fieldsContainer.replaceChildren(); for (const [colIdx, colInfo] of columns) { - const uniqueValues = Array.from(colInfo.values); - const isMixed = uniqueValues.length > 1; - - let valueDisplay = ''; - if (isMixed) { - valueDisplay = '(mixed values)'; - } else { - const val = uniqueValues[0]; - if (val === null) valueDisplay = 'NULL'; - else if (val instanceof Uint8Array) valueDisplay = '[BLOB]'; - else valueDisplay = String(val); - } + const valueDisplay = summarizeColumnValue(colInfo.values); const div = document.createElement('div'); div.className = 'form-field batch-field'; @@ -358,49 +335,8 @@ export async function applyBatchUpdate() { } } - const updates = []; - - // 2. Processing Phase - for (const cell of state.selectedCells) { - const input = inputsByCol.get(cell.colIdx); - if (!input) continue; - - const isNull = input.dataset.isnull === 'true'; - const isPatch = input.dataset.ispatch === 'true'; - const value = input.value; - - // Skip if empty and not explicitly set to NULL (and not patch with content) - if (value === "" && !isNull) continue; - - const colDef = state.tableColumns[cell.colIdx]; - - // Prepare value - let finalValue = value; - let operation = 'set'; - - if (isNull) { - finalValue = null; - } else if (isPatch) { - operation = 'json_patch'; - } else { - // Basic type coercion - if (colDef.type === 'INTEGER' || colDef.type === 'REAL' || colDef.type === 'NUMERIC') { - if (!isNaN(Number(value)) && value.trim() !== '') { - finalValue = Number(value); - } - } - } - - updates.push({ - rowId: cell.rowId, - column: colDef.name, - value: finalValue, - originalValue: cell.value, - operation, - rowIdx: cell.rowIdx, // Local metadata - colIdx: cell.colIdx // Local metadata - }); - } + // 2. Processing Phase — value coercion / NULL / json_patch (see batch-update-logic.js) + const updates = prepareBatchUpdates(state.selectedCells, inputsByCol, state.tableColumns); if (updates.length === 0) { updateStatus('No values entered for batch update'); diff --git a/core/ui/viewer.html b/core/ui/viewer.html index a085bbb..2e0bc8f 100644 --- a/core/ui/viewer.html +++ b/core/ui/viewer.html @@ -364,7 +364,7 @@ diff --git a/tests/unit/batch-update-logic.test.ts b/tests/unit/batch-update-logic.test.ts new file mode 100644 index 0000000..2592097 --- /dev/null +++ b/tests/unit/batch-update-logic.test.ts @@ -0,0 +1,101 @@ +/** + * Unit tests for the DOM-free batch-update logic extracted from sidebar.js. + * Covers the value-processing rules that drive the batch-update form. + */ +import { describe, it } from 'node:test'; +import assert from 'node:assert'; +import { + groupSelectedCellsByColumn, + summarizeColumnValue, + prepareBatchUpdates, +} from '../../core/ui/modules/batch-update-logic.js'; +import type { + BatchSelectedCell, + BatchColumnDef, + BatchInputLike, +} from '../../core/ui/modules/batch-update-logic.js'; + +const columns: BatchColumnDef[] = [ + { name: 'id', type: 'INTEGER' }, + { name: 'name', type: 'TEXT' }, + { name: 'price', type: 'REAL' }, + { name: 'meta', type: 'TEXT' }, +]; + +const cell = (rowIdx: number, colIdx: number, value: unknown): BatchSelectedCell => + ({ rowId: rowIdx + 1, rowIdx, colIdx, value }); + +const input = (value: string, opts: { isnull?: boolean; ispatch?: boolean } = {}): BatchInputLike => + ({ value, dataset: { isnull: opts.isnull ? 'true' : 'false', ispatch: opts.ispatch ? 'true' : 'false' } }); + +describe('groupSelectedCellsByColumn', () => { + it('groups cells by column with distinct value sets', () => { + const grouped = groupSelectedCellsByColumn( + [cell(0, 1, 'a'), cell(1, 1, 'b'), cell(2, 1, 'a'), cell(0, 0, 1)], + columns + ); + assert.strictEqual(grouped.size, 2); + assert.strictEqual(grouped.get(1)!.name, 'name'); + assert.deepStrictEqual([...grouped.get(1)!.values], ['a', 'b']); // distinct + assert.deepStrictEqual([...grouped.get(0)!.values], [1]); + }); +}); + +describe('summarizeColumnValue', () => { + it('shows the single shared value', () => { + assert.strictEqual(summarizeColumnValue(new Set(['hello'])), 'hello'); + assert.strictEqual(summarizeColumnValue(new Set([42])), '42'); + }); + it('shows NULL for null and [BLOB] for binary', () => { + assert.strictEqual(summarizeColumnValue(new Set([null])), 'NULL'); + assert.strictEqual(summarizeColumnValue(new Set([new Uint8Array([1, 2])])), '[BLOB]'); + }); + it('shows (mixed values) when the selection spans differing values', () => { + assert.strictEqual(summarizeColumnValue(new Set(['a', 'b'])), '(mixed values)'); + }); +}); + +describe('prepareBatchUpdates', () => { + it('coerces INTEGER columns to numbers (operation set)', () => { + const [u] = prepareBatchUpdates([cell(0, 0, 5)], new Map([[0, input('42')]]), columns); + assert.strictEqual(u.value, 42); + assert.strictEqual(typeof u.value, 'number'); + assert.strictEqual(u.operation, 'set'); + assert.strictEqual(u.column, 'id'); + assert.strictEqual(u.originalValue, 5); + }); + it('coerces REAL columns', () => { + const [u] = prepareBatchUpdates([cell(0, 2, 1)], new Map([[2, input('3.14')]]), columns); + assert.strictEqual(u.value, 3.14); + }); + it('does not coerce non-numeric input in a numeric column', () => { + const [u] = prepareBatchUpdates([cell(0, 0, 1)], new Map([[0, input('abc')]]), columns); + assert.strictEqual(u.value, 'abc'); + }); + it('leaves TEXT values as strings', () => { + const [u] = prepareBatchUpdates([cell(0, 1, 'x')], new Map([[1, input('hello')]]), columns); + assert.strictEqual(u.value, 'hello'); + }); + it('sets value to null when the field is marked NULL', () => { + const [u] = prepareBatchUpdates([cell(0, 1, 'x')], new Map([[1, input('', { isnull: true })]]), columns); + assert.strictEqual(u.value, null); + assert.strictEqual(u.operation, 'set'); + }); + it('tags json_patch and keeps the raw patch string', () => { + const [u] = prepareBatchUpdates([cell(0, 3, '{}')], new Map([[3, input('{"a":1}', { ispatch: true })]]), columns); + assert.strictEqual(u.operation, 'json_patch'); + assert.strictEqual(u.value, '{"a":1}'); + }); + it('skips cells left blank unless explicitly NULL', () => { + assert.strictEqual(prepareBatchUpdates([cell(0, 1, 'x')], new Map([[1, input('')]]), columns).length, 0); + }); + it('skips cells whose column has no input', () => { + assert.strictEqual(prepareBatchUpdates([cell(0, 1, 'x')], new Map(), columns).length, 0); + }); + it('processes multiple cells and preserves row/col metadata', () => { + const updates = prepareBatchUpdates([cell(0, 1, 'x'), cell(1, 1, 'y')], new Map([[1, input('Z')]]), columns); + assert.strictEqual(updates.length, 2); + assert.deepStrictEqual(updates.map(u => u.rowIdx), [0, 1]); + assert.strictEqual(updates[0].colIdx, 1); + }); +}); diff --git a/website/public/sqlite-viewer/viewer.html b/website/public/sqlite-viewer/viewer.html index 7286041..209e12d 100644 --- a/website/public/sqlite-viewer/viewer.html +++ b/website/public/sqlite-viewer/viewer.html @@ -364,7 +364,7 @@ From 6c4e9541b03c8670f0dce46f1d092c857151066e Mon Sep 17 00:00:00 2001 From: zknpr Date: Sat, 30 May 2026 22:45:12 +0200 Subject: [PATCH 2/3] test(ui): harden batch-update logic against edge cases Applies the defensive findings from Gemini's review of this PR: - groupSelectedCellsByColumn / prepareBatchUpdates: skip cells whose colDef is missing (stale/out-of-bounds selection, e.g. after a column drop) rather than throwing - summarizeColumnValue: return '' for an empty value set - prepareBatchUpdates: tolerate an input without a `dataset` - `dataset` made optional in the .d.ts + 4 edge-case unit tests (suite: 328 passing). Co-Authored-By: Claude Opus 4.8 (1M context) --- core/ui/modules/batch-update-logic.d.ts | 2 +- core/ui/modules/batch-update-logic.js | 14 +++++++++----- core/ui/viewer.html | 18 +++++++++--------- tests/unit/batch-update-logic.test.ts | 20 ++++++++++++++++++++ website/public/sqlite-viewer/viewer.html | 12 ++++++------ 5 files changed, 45 insertions(+), 21 deletions(-) diff --git a/core/ui/modules/batch-update-logic.d.ts b/core/ui/modules/batch-update-logic.d.ts index ceaa29a..d451b4c 100644 --- a/core/ui/modules/batch-update-logic.d.ts +++ b/core/ui/modules/batch-update-logic.d.ts @@ -17,7 +17,7 @@ export interface BatchColumnDef { /** Minimal shape of a batch-field (real element or test stand-in). */ export interface BatchInputLike { value: string; - dataset: { isnull?: string; ispatch?: string }; + dataset?: { isnull?: string; ispatch?: string }; } export interface BatchColumnInfo { diff --git a/core/ui/modules/batch-update-logic.js b/core/ui/modules/batch-update-logic.js index 7c5bf0e..5313855 100644 --- a/core/ui/modules/batch-update-logic.js +++ b/core/ui/modules/batch-update-logic.js @@ -17,8 +17,9 @@ export function groupSelectedCellsByColumn(selectedCells, tableColumns) { const columns = new Map(); for (const cell of selectedCells) { + const colDef = tableColumns && tableColumns[cell.colIdx]; + if (!colDef) continue; // skip stale/out-of-bounds selections (e.g. after a column drop) if (!columns.has(cell.colIdx)) { - const colDef = tableColumns[cell.colIdx]; columns.set(cell.colIdx, { name: colDef.name, type: colDef.type, @@ -36,7 +37,8 @@ export function groupSelectedCellsByColumn(selectedCells, tableColumns) { * single shared value rendered as NULL / [BLOB] / its string form. */ export function summarizeColumnValue(values) { - const uniqueValues = Array.from(values); + const uniqueValues = Array.from(values || []); + if (uniqueValues.length === 0) return ''; if (uniqueValues.length > 1) return '(mixed values)'; const val = uniqueValues[0]; if (val === null) return 'NULL'; @@ -59,14 +61,16 @@ export function prepareBatchUpdates(selectedCells, inputsByCol, tableColumns) { const input = inputsByCol.get(cell.colIdx); if (!input) continue; - const isNull = input.dataset.isnull === 'true'; - const isPatch = input.dataset.ispatch === 'true'; + const dataset = input.dataset || {}; + const isNull = dataset.isnull === 'true'; + const isPatch = dataset.ispatch === 'true'; const value = input.value; // Skip cells left blank unless they were explicitly set to NULL. if (value === '' && !isNull) continue; - const colDef = tableColumns[cell.colIdx]; + const colDef = tableColumns && tableColumns[cell.colIdx]; + if (!colDef) continue; // skip stale/out-of-bounds selections let finalValue = value; let operation = 'set'; diff --git a/core/ui/viewer.html b/core/ui/viewer.html index 2e0bc8f..c4e0c63 100644 --- a/core/ui/viewer.html +++ b/core/ui/viewer.html @@ -364,7 +364,7 @@ diff --git a/tests/unit/batch-update-logic.test.ts b/tests/unit/batch-update-logic.test.ts index 2592097..2410073 100644 --- a/tests/unit/batch-update-logic.test.ts +++ b/tests/unit/batch-update-logic.test.ts @@ -99,3 +99,23 @@ describe('prepareBatchUpdates', () => { assert.strictEqual(updates[0].colIdx, 1); }); }); + +describe('batch-update-logic hardening (edge cases)', () => { + it('groupSelectedCellsByColumn skips out-of-bounds column indices', () => { + const grouped = groupSelectedCellsByColumn([cell(0, 99, 'x'), cell(0, 1, 'a')], columns); + assert.strictEqual(grouped.size, 1); + assert.ok(grouped.has(1)); + assert.ok(!grouped.has(99)); + }); + it('summarizeColumnValue returns empty string for an empty set', () => { + assert.strictEqual(summarizeColumnValue(new Set()), ''); + }); + it('prepareBatchUpdates skips cells whose column is out of bounds (e.g. after a column drop)', () => { + assert.strictEqual(prepareBatchUpdates([cell(0, 99, 'x')], new Map([[99, input('v')]]), columns).length, 0); + }); + it('prepareBatchUpdates tolerates an input without a dataset', () => { + const [u] = prepareBatchUpdates([cell(0, 1, 'x')], new Map([[1, { value: 'hi' } as BatchInputLike]]), columns); + assert.strictEqual(u.value, 'hi'); + assert.strictEqual(u.operation, 'set'); + }); +}); diff --git a/website/public/sqlite-viewer/viewer.html b/website/public/sqlite-viewer/viewer.html index 209e12d..4631ab7 100644 --- a/website/public/sqlite-viewer/viewer.html +++ b/website/public/sqlite-viewer/viewer.html @@ -385,7 +385,7 @@ No data This table is empty - `,e}function Ot(e,t,o){let l=document.createElement("thead");l.className="grid-header";let a=document.createElement("tr"),s=document.createElement("th");s.className="header-cell row-number-header",Object.assign(s.style,{width:`${e}px`,minWidth:`${e}px`,maxWidth:`${e}px`,position:"sticky",left:"0",top:"0",zIndex:"11",background:"var(--bg-secondary)"}),s.title="Click to select all rows",s.innerHTML='
#
',a.appendChild(s);for(let i of t){let r=n.sortedColumn===i.name,c=n.pinnedColumns.has(i.name),d=n.selectedColumns.has(i.name),m=n.columnWidths[i.name]||120,g=n.columnFilters[i.name]||"",h=document.createElement("th");h.className=`header-cell ${c?"pinned":""} ${d?"column-selected":""}`,Object.assign(h.style,{width:`${m}px`,minWidth:`${m}px`,maxWidth:`${m}px`}),c&&(h.style.position="sticky",h.style.left=`${o.get(i.name)}px`),h.dataset.column=i.name;let p=J(i.name),f=J(g),b=r?`${n.sortAscending?"\u25B2":"\u25BC"}`:"",I=i.isPrimaryKey?'':"",x=c?"pinned":"",C=c?"Unpin column":"Pin column";h.innerHTML=` + `,e}function Ot(e,t,o){let l=document.createElement("thead");l.className="grid-header";let a=document.createElement("tr"),s=document.createElement("th");s.className="header-cell row-number-header",Object.assign(s.style,{width:`${e}px`,minWidth:`${e}px`,maxWidth:`${e}px`,position:"sticky",left:"0",top:"0",zIndex:"11",background:"var(--bg-secondary)"}),s.title="Click to select all rows",s.innerHTML='
#
',a.appendChild(s);for(let i of t){let r=n.sortedColumn===i.name,d=n.pinnedColumns.has(i.name),c=n.selectedColumns.has(i.name),m=n.columnWidths[i.name]||120,g=n.columnFilters[i.name]||"",f=document.createElement("th");f.className=`header-cell ${d?"pinned":""} ${c?"column-selected":""}`,Object.assign(f.style,{width:`${m}px`,minWidth:`${m}px`,maxWidth:`${m}px`}),d&&(f.style.position="sticky",f.style.left=`${o.get(i.name)}px`),f.dataset.column=i.name;let p=J(i.name),h=J(g),b=r?`${n.sortAscending?"\u25B2":"\u25BC"}`:"",I=i.isPrimaryKey?'':"",x=d?"pinned":"",C=d?"Unpin column":"Pin column";f.innerHTML=`
${I}${p}${b} @@ -393,16 +393,16 @@
- +
- `,a.appendChild(h)}return l.appendChild(a),l}function zt(e,t,o,l,a,s,i,r){let c=document.createElement("tbody"),d=[];for(let p=0;p({idx:f,rowId:T(p,f)})).filter(p=>n.pinnedRowIds.has(p.rowId)),...n.gridData.map((p,f)=>({idx:f,rowId:T(p,f)})).filter(p=>!n.pinnedRowIds.has(p.rowId))],h=document.createDocumentFragment();for(let{idx:p,rowId:f}of g){let b=n.gridData[p],I=n.selectedRowIds.has(f),x=n.pinnedRowIds.has(f),C=document.createElement("tr");C.id=`row-${p}`,C.className=`data-row ${I?"selected":""} ${x?"pinned":""}`,C.dataset.rowid=f,C.dataset.rowidx=p,x&&(C.style.top=`${m.get(f)}px`);let k=document.createElement("td");k.className="data-cell row-number",Object.assign(k.style,{width:`${l}px`,minWidth:`${l}px`,maxWidth:`${l}px`,position:"sticky",left:"0",zIndex:x?"8":"2"});let L=n.currentPageIndex*n.rowsPerPage+p+1;k.appendChild(document.createTextNode(String(L)));let w=document.createElement("span");w.className=`pin-icon codicon codicon-pin ${x?"pinned":""}`,w.title=x?"Unpin row":"Pin row",k.appendChild(w),C.appendChild(k);for(let D=0;Dw&&w.trim()!=="");if(r.innerHTML="",n.gridData.length===0&&!h&&n.tableColumns.length===0){r.appendChild(Ut());return}let p=new Set;if(n.selectedCells.length>0)for(let w of n.selectedCells)p.add(`${w.rowIdx},${w.colIdx}`);let f=document.createElement("table");if(f.className="data-grid",Object.keys(n.columnWidths).length===0&&n.gridData.length>0)for(let w of n.tableColumns){let D=w.name.length,N=w.isPrimaryKey?86:70,W=D*8+N;n.columnWidths[w.name]=Math.max(80,Math.min(250,W))}let b=[...n.tableColumns.filter(w=>n.pinnedColumns.has(w.name)),...n.tableColumns.filter(w=>!n.pinnedColumns.has(w.name))],I=new Map,x=i-1;for(let w of b)n.pinnedColumns.has(w.name)&&(I.set(w.name,x),x+=n.columnWidths[w.name]||120);let C=new Map;n.tableColumns.forEach((w,D)=>C.set(w.name,D));let k=Ot(i,b,I);f.appendChild(k);let L=zt(b,C,I,i,52,26,p,h);f.appendChild(L),r.appendChild(f),r.scrollLeft=m,r.scrollTop=g,Fe()}function Ue(){document.getElementById("pageIndicator").textContent=`${n.currentPageIndex+1} / ${n.totalPageCount}`,document.getElementById("btnFirst").disabled=n.currentPageIndex===0,document.getElementById("btnPrev").disabled=n.currentPageIndex===0,document.getElementById("btnNext").disabled=n.currentPageIndex>=n.totalPageCount-1,document.getElementById("btnLast").disabled=n.currentPageIndex>=n.totalPageCount-1}async function K(){if(n.selectedTable)try{let e=await y.getTableInfo(n.selectedTable);n.tableColumns=e.map(o=>({cid:o.ordinal,name:o.identifier,type:o.declaredType,notnull:o.isRequired,dflt_value:o.defaultExpression,isPrimaryKey:o.primaryKeyPosition>0})).sort((o,l)=>o.cid-l.cid);let t=new Set(n.tableColumns.map(o=>o.name));n.sortedColumn&&!t.has(n.sortedColumn)&&(n.sortedColumn=null,n.sortAscending=!0);for(let o of Object.keys(n.columnFilters))t.has(o)||delete n.columnFilters[o]}catch(e){console.error("Error loading columns:",e),u("Error loading columns")}}async function v(e=!0,t=!0){if(!n.selectedTable)return;let o=document.getElementById("gridContainer");t&&o&&o.querySelector(".data-grid")&&(n.scrollPosition.left=o.scrollLeft,n.scrollPosition.top=o.scrollTop),e&&(n.isLoadingData=!0,$e()),R();try{let l=[];for(let[m,g]of Object.entries(n.columnFilters))g&&g.trim()&&l.push({column:m,value:g});let a={filters:l,globalFilter:n.filterQuery,columns:n.tableColumns.map(m=>m.name)};n.totalRecordCount=await y.fetchTableCount(n.selectedTable,a),n.totalPageCount=Math.max(1,Math.ceil(n.totalRecordCount/n.rowsPerPage)),n.currentPageIndex>=n.totalPageCount&&(n.currentPageIndex=Math.max(0,n.totalPageCount-1));let s=n.selectedTableType==="table",i=n.tableColumns.map(m=>m.name),c={columns:s?["rowid",...i]:i,orderBy:n.sortedColumn,orderDir:n.sortAscending?"ASC":"DESC",limit:n.rowsPerPage,offset:n.currentPageIndex*n.rowsPerPage,filters:l,globalFilter:n.filterQuery},d=await y.fetchTableData(n.selectedTable,c);n.gridData=d.rows||[],!e&&o&&o.querySelector(".data-grid")&&(n.scrollPosition.left=o.scrollLeft,n.scrollPosition.top=o.scrollTop),!e&&n.editingCellInfo||z(n.scrollPosition.top,n.scrollPosition.left),o&&(o.scrollLeft=n.scrollPosition.left,o.scrollTop=n.scrollPosition.top),Ue(),u(`${n.totalRecordCount} records`)}catch(l){console.error("Error loading data:",l),u(`Error: ${l.message}`),ne(l.message)}finally{e&&(n.isLoadingData=!1)}}var S={PNG:[137,80,78,71,13,10,26,10],JPEG:[255,216,255],GIF:[71,73,70,56],BMP:[66,77],RIFF:[82,73,70,70],WEBP:[87,69,66,80],PDF:[37,80,68,70,45],ID3:[73,68,51],MP3_SYNC1:[255,251],MP3_SYNC2:[255,243],MP3_SYNC3:[255,242],OGG:[79,103,103,83],WAVE:[87,65,86,69],FLAC:[102,76,97,67],FTYP:[102,116,121,112],WEBM:[26,69,223,163],AVI:[65,86,73,32]},le=class{constructor(){this.currentObjectUrl=null,this.modal=document.getElementById("blob-inspector-modal"),this.previewContainer=document.getElementById("tab-preview"),this.hexContainer=document.querySelector(".hex-dump"),this.infoContainer=document.getElementById("blob-info"),this.currentData=null,this.currentType=null,this.currentRowId=null,this.currentColName=null,this.currentCellInfo=null,this.isUploading=!1,this.setupEventListeners()}setupEventListeners(){this.modal.querySelectorAll(".modal-close").forEach(l=>{l.addEventListener("click",()=>this.close())}),this.modal.querySelectorAll(".tab-btn").forEach(l=>{l.addEventListener("click",a=>{let s=a.target.dataset.tab;this.switchTab(s)})});let t=document.getElementById("blob-download-btn");t&&t.addEventListener("click",()=>this.download());let o=document.getElementById("blob-replace-btn");o&&o.addEventListener("click",()=>this.handleReplace())}setUploadState(t){this.isUploading=t;let o=document.getElementById("blob-replace-btn"),l=document.getElementById("blob-download-btn");o&&(o.disabled=t,o.textContent=t?"Uploading...":"Replace"),l&&(l.disabled=t)}async handleReplace(){if(!this.isUploading)try{if(((await y.getExtensionSettings())?.fileOperations||"native")==="web")this.showFileInput();else{let l=await y.selectFile();if(l){let a=l.data;if(!(a instanceof Uint8Array)){if(Array.isArray(a))a=new Uint8Array(a);else if(a&&typeof a=="object"){let i=Object.keys(a).filter(r=>!isNaN(parseInt(r,10))).sort((r,c)=>parseInt(r,10)-parseInt(c,10)).map(r=>a[r]);a=new Uint8Array(i)}}let s={name:l.name,arrayBuffer:async()=>a.buffer};await this.uploadFile(s)}}}catch(t){console.error("Replace failed:",t),u(`Replace failed: ${t.message}`)}}showFileInput(){let t=document.createElement("input");t.type="file",t.onchange=async o=>{let l=o.target.files[0];l&&await this.uploadFile(l)},t.click()}async uploadFile(t){if(!(!this.currentRowId||!this.currentColName)&&!this.isUploading){this.setUploadState(!0);try{u(`Reading ${t.name}...`);let o=await t.arrayBuffer(),l=new Uint8Array(o),a=l.length/(1024*1024),s=50;if(a>s)throw new Error(`File too large (${a.toFixed(1)}MB). Maximum size is ${s}MB to prevent freezing.`);a>10?u(`Uploading ${t.name} (${a.toFixed(1)}MB - this may take a moment)...`):u(`Uploading ${t.name}...`);let{rowIdx:i,colIdx:r}=this.currentCellInfo,c=this.currentData;await y.updateCell(n.selectedTable,this.currentRowId,this.currentColName,l,c),n.gridData&&n.gridData[i]&&(n.gridData[i][r+B()]=l),this.inspect(l,this.currentRowId,this.currentColName,i,r),u(`Replaced with ${t.name}`)}catch(o){console.error("Replace failed:",o);let l=o.message||String(o);l.includes("timeout")&&(l="Upload timed out. Try a smaller file or increase the timeout."),u(`Replace failed: ${l}`)}finally{this.setUploadState(!1)}}}close(){this.modal.classList.add("hidden"),this.cleanup()}cleanup(){this.setUploadState(!1),this.currentObjectUrl&&(URL.revokeObjectURL(this.currentObjectUrl),this.currentObjectUrl=null),this.previewContainer.innerHTML="",this.hexContainer.value="",this.infoContainer.textContent="",this.currentData=null}switchTab(t){this.modal.querySelectorAll(".tab-btn").forEach(a=>{a.dataset.tab===t?(a.classList.add("active"),a.style.borderBottom="2px solid var(--accent-color)",a.style.color="var(--text-primary)"):(a.classList.remove("active"),a.style.borderBottom="none",a.style.color="var(--text-secondary)")});let o=document.getElementById("tab-preview"),l=document.getElementById("tab-hex");t==="preview"?(o.style.display="flex",l.style.display="none"):(o.style.display="none",l.style.display="block")}async download(){if(!this.currentData)return;let t=this.currentType?.ext||"bin",o=`blob_${this.currentRowId}.${t}`;try{((await y.getExtensionSettings())?.fileOperations||"native")==="web"?(this.downloadBlob(this.currentData,o),u(`Downloaded ${o}`)):(await y.saveFile(o,this.currentData),u(`Saved ${o}`))}catch(l){console.error("Download failed:",l),u(`Download failed: ${l.message}`)}}downloadBlob(t,o){let l=new Blob([t]),a=URL.createObjectURL(l),s=document.createElement("a");s.href=a,s.download=o,s.click(),URL.revokeObjectURL(a)}inspect(t,o,l,a,s){this.cleanup(),this.currentRowId=o,this.currentColName=l,this.currentCellInfo={rowIdx:a,colIdx:s},this.modal.classList.remove("hidden"),this.switchTab("preview");let i=t instanceof Uint8Array?t:new Uint8Array(t);this.currentData=i;let r=this.detectType(i);this.currentType=r;let c=this.formatSize(i.length);this.infoContainer.textContent=`${l} (Row ${o}) | ${r.mime||"Unknown Type"} | ${c}`,this.renderPreview(i,r),this.renderHex(i)}detectType(t){if(this.checkSignature(t,S.PNG))return{mime:"image/png",type:"image",ext:"png"};if(this.checkSignature(t,S.JPEG))return{mime:"image/jpeg",type:"image",ext:"jpg"};if(this.checkSignature(t,S.GIF))return{mime:"image/gif",type:"image",ext:"gif"};if(this.checkSignature(t,S.BMP))return{mime:"image/bmp",type:"image",ext:"bmp"};if(this.checkSignature(t,S.RIFF)&&this.checkSignature(t.subarray(8),S.WEBP))return{mime:"image/webp",type:"image",ext:"webp"};if(this.checkSignature(t,S.PDF))return{mime:"application/pdf",type:"pdf",ext:"pdf"};if(this.checkSignature(t,S.ID3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(t,S.MP3_SYNC1)||this.checkSignature(t,S.MP3_SYNC2)||this.checkSignature(t,S.MP3_SYNC3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(t,S.OGG))return{mime:"audio/ogg",type:"audio",ext:"ogg"};if(this.checkSignature(t,S.RIFF)&&this.checkSignature(t.subarray(8),S.WAVE))return{mime:"audio/wav",type:"audio",ext:"wav"};if(this.checkSignature(t,S.FLAC))return{mime:"audio/flac",type:"audio",ext:"flac"};if(this.checkSignature(t.subarray(4),S.FTYP)){let o=String.fromCharCode(...t.subarray(8,12));return o.startsWith("mp4")||o==="isom"||o==="avc1"||o==="M4V "?{mime:"video/mp4",type:"video",ext:"mp4"}:o==="qt "||o.startsWith("M4A")?{mime:"video/quicktime",type:"video",ext:"mov"}:{mime:"video/mp4",type:"video",ext:"mp4"}}if(this.checkSignature(t,S.WEBM))return{mime:"video/webm",type:"video",ext:"webm"};if(this.checkSignature(t,S.RIFF)&&this.checkSignature(t.subarray(8),S.AVI))return{mime:"video/avi",type:"video",ext:"avi"};if(this.isText(t)){try{let o=new TextDecoder().decode(t),l=JSON.parse(o);if(typeof l=="object"&&l!==null)return{mime:"application/json",type:"json",ext:"json"}}catch{}return{mime:"text/plain",type:"text",ext:"txt"}}return{mime:"application/octet-stream",type:"binary",ext:"bin"}}checkSignature(t,o){if(t.lengththis.download()),l.appendChild(a),l.appendChild(s),l.appendChild(i),this.previewContainer.appendChild(l)}else{let l=document.createElement("div");l.className="empty-view";let a=document.createElement("span");a.className="codicon codicon-file-binary",a.style.fontSize="48px",a.style.opacity="0.5";let s=document.createElement("span");s.style.marginTop="12px",s.textContent="Binary Data";let i=document.createElement("span");i.style.fontSize="12px",i.style.opacity="0.7",i.textContent="Use Hex view to inspect",l.appendChild(a),l.appendChild(s),l.appendChild(i),this.previewContainer.appendChild(l)}}renderHex(t){if(!this.hexContainer)return;let o=16*1e3,l="",a=t.subarray(0,o);for(let s=0;s=32&&p<=126?String.fromCharCode(p):".")}else r.push(" "),c.push(" ");let d=r.slice(0,8).join(" "),m=r.slice(8).join(" "),g=c.join("");l+=`${i} ${d} ${m} |${g}| + `,a.appendChild(f)}return l.appendChild(a),l}function zt(e,t,o,l,a,s,i,r){let d=document.createElement("tbody"),c=[];for(let p=0;p({idx:h,rowId:T(p,h)})).filter(p=>n.pinnedRowIds.has(p.rowId)),...n.gridData.map((p,h)=>({idx:h,rowId:T(p,h)})).filter(p=>!n.pinnedRowIds.has(p.rowId))],f=document.createDocumentFragment();for(let{idx:p,rowId:h}of g){let b=n.gridData[p],I=n.selectedRowIds.has(h),x=n.pinnedRowIds.has(h),C=document.createElement("tr");C.id=`row-${p}`,C.className=`data-row ${I?"selected":""} ${x?"pinned":""}`,C.dataset.rowid=h,C.dataset.rowidx=p,x&&(C.style.top=`${m.get(h)}px`);let k=document.createElement("td");k.className="data-cell row-number",Object.assign(k.style,{width:`${l}px`,minWidth:`${l}px`,maxWidth:`${l}px`,position:"sticky",left:"0",zIndex:x?"8":"2"});let L=n.currentPageIndex*n.rowsPerPage+p+1;k.appendChild(document.createTextNode(String(L)));let w=document.createElement("span");w.className=`pin-icon codicon codicon-pin ${x?"pinned":""}`,w.title=x?"Unpin row":"Pin row",k.appendChild(w),C.appendChild(k);for(let D=0;Dw&&w.trim()!=="");if(r.innerHTML="",n.gridData.length===0&&!f&&n.tableColumns.length===0){r.appendChild(Ut());return}let p=new Set;if(n.selectedCells.length>0)for(let w of n.selectedCells)p.add(`${w.rowIdx},${w.colIdx}`);let h=document.createElement("table");if(h.className="data-grid",Object.keys(n.columnWidths).length===0&&n.gridData.length>0)for(let w of n.tableColumns){let D=w.name.length,N=w.isPrimaryKey?86:70,W=D*8+N;n.columnWidths[w.name]=Math.max(80,Math.min(250,W))}let b=[...n.tableColumns.filter(w=>n.pinnedColumns.has(w.name)),...n.tableColumns.filter(w=>!n.pinnedColumns.has(w.name))],I=new Map,x=i-1;for(let w of b)n.pinnedColumns.has(w.name)&&(I.set(w.name,x),x+=n.columnWidths[w.name]||120);let C=new Map;n.tableColumns.forEach((w,D)=>C.set(w.name,D));let k=Ot(i,b,I);h.appendChild(k);let L=zt(b,C,I,i,52,26,p,f);h.appendChild(L),r.appendChild(h),r.scrollLeft=m,r.scrollTop=g,Fe()}function Ue(){document.getElementById("pageIndicator").textContent=`${n.currentPageIndex+1} / ${n.totalPageCount}`,document.getElementById("btnFirst").disabled=n.currentPageIndex===0,document.getElementById("btnPrev").disabled=n.currentPageIndex===0,document.getElementById("btnNext").disabled=n.currentPageIndex>=n.totalPageCount-1,document.getElementById("btnLast").disabled=n.currentPageIndex>=n.totalPageCount-1}async function K(){if(n.selectedTable)try{let e=await y.getTableInfo(n.selectedTable);n.tableColumns=e.map(o=>({cid:o.ordinal,name:o.identifier,type:o.declaredType,notnull:o.isRequired,dflt_value:o.defaultExpression,isPrimaryKey:o.primaryKeyPosition>0})).sort((o,l)=>o.cid-l.cid);let t=new Set(n.tableColumns.map(o=>o.name));n.sortedColumn&&!t.has(n.sortedColumn)&&(n.sortedColumn=null,n.sortAscending=!0);for(let o of Object.keys(n.columnFilters))t.has(o)||delete n.columnFilters[o]}catch(e){console.error("Error loading columns:",e),u("Error loading columns")}}async function v(e=!0,t=!0){if(!n.selectedTable)return;let o=document.getElementById("gridContainer");t&&o&&o.querySelector(".data-grid")&&(n.scrollPosition.left=o.scrollLeft,n.scrollPosition.top=o.scrollTop),e&&(n.isLoadingData=!0,$e()),R();try{let l=[];for(let[m,g]of Object.entries(n.columnFilters))g&&g.trim()&&l.push({column:m,value:g});let a={filters:l,globalFilter:n.filterQuery,columns:n.tableColumns.map(m=>m.name)};n.totalRecordCount=await y.fetchTableCount(n.selectedTable,a),n.totalPageCount=Math.max(1,Math.ceil(n.totalRecordCount/n.rowsPerPage)),n.currentPageIndex>=n.totalPageCount&&(n.currentPageIndex=Math.max(0,n.totalPageCount-1));let s=n.selectedTableType==="table",i=n.tableColumns.map(m=>m.name),d={columns:s?["rowid",...i]:i,orderBy:n.sortedColumn,orderDir:n.sortAscending?"ASC":"DESC",limit:n.rowsPerPage,offset:n.currentPageIndex*n.rowsPerPage,filters:l,globalFilter:n.filterQuery},c=await y.fetchTableData(n.selectedTable,d);n.gridData=c.rows||[],!e&&o&&o.querySelector(".data-grid")&&(n.scrollPosition.left=o.scrollLeft,n.scrollPosition.top=o.scrollTop),!e&&n.editingCellInfo||z(n.scrollPosition.top,n.scrollPosition.left),o&&(o.scrollLeft=n.scrollPosition.left,o.scrollTop=n.scrollPosition.top),Ue(),u(`${n.totalRecordCount} records`)}catch(l){console.error("Error loading data:",l),u(`Error: ${l.message}`),ne(l.message)}finally{e&&(n.isLoadingData=!1)}}var S={PNG:[137,80,78,71,13,10,26,10],JPEG:[255,216,255],GIF:[71,73,70,56],BMP:[66,77],RIFF:[82,73,70,70],WEBP:[87,69,66,80],PDF:[37,80,68,70,45],ID3:[73,68,51],MP3_SYNC1:[255,251],MP3_SYNC2:[255,243],MP3_SYNC3:[255,242],OGG:[79,103,103,83],WAVE:[87,65,86,69],FLAC:[102,76,97,67],FTYP:[102,116,121,112],WEBM:[26,69,223,163],AVI:[65,86,73,32]},le=class{constructor(){this.currentObjectUrl=null,this.modal=document.getElementById("blob-inspector-modal"),this.previewContainer=document.getElementById("tab-preview"),this.hexContainer=document.querySelector(".hex-dump"),this.infoContainer=document.getElementById("blob-info"),this.currentData=null,this.currentType=null,this.currentRowId=null,this.currentColName=null,this.currentCellInfo=null,this.isUploading=!1,this.setupEventListeners()}setupEventListeners(){this.modal.querySelectorAll(".modal-close").forEach(l=>{l.addEventListener("click",()=>this.close())}),this.modal.querySelectorAll(".tab-btn").forEach(l=>{l.addEventListener("click",a=>{let s=a.target.dataset.tab;this.switchTab(s)})});let t=document.getElementById("blob-download-btn");t&&t.addEventListener("click",()=>this.download());let o=document.getElementById("blob-replace-btn");o&&o.addEventListener("click",()=>this.handleReplace())}setUploadState(t){this.isUploading=t;let o=document.getElementById("blob-replace-btn"),l=document.getElementById("blob-download-btn");o&&(o.disabled=t,o.textContent=t?"Uploading...":"Replace"),l&&(l.disabled=t)}async handleReplace(){if(!this.isUploading)try{if(((await y.getExtensionSettings())?.fileOperations||"native")==="web")this.showFileInput();else{let l=await y.selectFile();if(l){let a=l.data;if(!(a instanceof Uint8Array)){if(Array.isArray(a))a=new Uint8Array(a);else if(a&&typeof a=="object"){let i=Object.keys(a).filter(r=>!isNaN(parseInt(r,10))).sort((r,d)=>parseInt(r,10)-parseInt(d,10)).map(r=>a[r]);a=new Uint8Array(i)}}let s={name:l.name,arrayBuffer:async()=>a.buffer};await this.uploadFile(s)}}}catch(t){console.error("Replace failed:",t),u(`Replace failed: ${t.message}`)}}showFileInput(){let t=document.createElement("input");t.type="file",t.onchange=async o=>{let l=o.target.files[0];l&&await this.uploadFile(l)},t.click()}async uploadFile(t){if(!(!this.currentRowId||!this.currentColName)&&!this.isUploading){this.setUploadState(!0);try{u(`Reading ${t.name}...`);let o=await t.arrayBuffer(),l=new Uint8Array(o),a=l.length/(1024*1024),s=50;if(a>s)throw new Error(`File too large (${a.toFixed(1)}MB). Maximum size is ${s}MB to prevent freezing.`);a>10?u(`Uploading ${t.name} (${a.toFixed(1)}MB - this may take a moment)...`):u(`Uploading ${t.name}...`);let{rowIdx:i,colIdx:r}=this.currentCellInfo,d=this.currentData;await y.updateCell(n.selectedTable,this.currentRowId,this.currentColName,l,d),n.gridData&&n.gridData[i]&&(n.gridData[i][r+B()]=l),this.inspect(l,this.currentRowId,this.currentColName,i,r),u(`Replaced with ${t.name}`)}catch(o){console.error("Replace failed:",o);let l=o.message||String(o);l.includes("timeout")&&(l="Upload timed out. Try a smaller file or increase the timeout."),u(`Replace failed: ${l}`)}finally{this.setUploadState(!1)}}}close(){this.modal.classList.add("hidden"),this.cleanup()}cleanup(){this.setUploadState(!1),this.currentObjectUrl&&(URL.revokeObjectURL(this.currentObjectUrl),this.currentObjectUrl=null),this.previewContainer.innerHTML="",this.hexContainer.value="",this.infoContainer.textContent="",this.currentData=null}switchTab(t){this.modal.querySelectorAll(".tab-btn").forEach(a=>{a.dataset.tab===t?(a.classList.add("active"),a.style.borderBottom="2px solid var(--accent-color)",a.style.color="var(--text-primary)"):(a.classList.remove("active"),a.style.borderBottom="none",a.style.color="var(--text-secondary)")});let o=document.getElementById("tab-preview"),l=document.getElementById("tab-hex");t==="preview"?(o.style.display="flex",l.style.display="none"):(o.style.display="none",l.style.display="block")}async download(){if(!this.currentData)return;let t=this.currentType?.ext||"bin",o=`blob_${this.currentRowId}.${t}`;try{((await y.getExtensionSettings())?.fileOperations||"native")==="web"?(this.downloadBlob(this.currentData,o),u(`Downloaded ${o}`)):(await y.saveFile(o,this.currentData),u(`Saved ${o}`))}catch(l){console.error("Download failed:",l),u(`Download failed: ${l.message}`)}}downloadBlob(t,o){let l=new Blob([t]),a=URL.createObjectURL(l),s=document.createElement("a");s.href=a,s.download=o,s.click(),URL.revokeObjectURL(a)}inspect(t,o,l,a,s){this.cleanup(),this.currentRowId=o,this.currentColName=l,this.currentCellInfo={rowIdx:a,colIdx:s},this.modal.classList.remove("hidden"),this.switchTab("preview");let i=t instanceof Uint8Array?t:new Uint8Array(t);this.currentData=i;let r=this.detectType(i);this.currentType=r;let d=this.formatSize(i.length);this.infoContainer.textContent=`${l} (Row ${o}) | ${r.mime||"Unknown Type"} | ${d}`,this.renderPreview(i,r),this.renderHex(i)}detectType(t){if(this.checkSignature(t,S.PNG))return{mime:"image/png",type:"image",ext:"png"};if(this.checkSignature(t,S.JPEG))return{mime:"image/jpeg",type:"image",ext:"jpg"};if(this.checkSignature(t,S.GIF))return{mime:"image/gif",type:"image",ext:"gif"};if(this.checkSignature(t,S.BMP))return{mime:"image/bmp",type:"image",ext:"bmp"};if(this.checkSignature(t,S.RIFF)&&this.checkSignature(t.subarray(8),S.WEBP))return{mime:"image/webp",type:"image",ext:"webp"};if(this.checkSignature(t,S.PDF))return{mime:"application/pdf",type:"pdf",ext:"pdf"};if(this.checkSignature(t,S.ID3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(t,S.MP3_SYNC1)||this.checkSignature(t,S.MP3_SYNC2)||this.checkSignature(t,S.MP3_SYNC3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(t,S.OGG))return{mime:"audio/ogg",type:"audio",ext:"ogg"};if(this.checkSignature(t,S.RIFF)&&this.checkSignature(t.subarray(8),S.WAVE))return{mime:"audio/wav",type:"audio",ext:"wav"};if(this.checkSignature(t,S.FLAC))return{mime:"audio/flac",type:"audio",ext:"flac"};if(this.checkSignature(t.subarray(4),S.FTYP)){let o=String.fromCharCode(...t.subarray(8,12));return o.startsWith("mp4")||o==="isom"||o==="avc1"||o==="M4V "?{mime:"video/mp4",type:"video",ext:"mp4"}:o==="qt "||o.startsWith("M4A")?{mime:"video/quicktime",type:"video",ext:"mov"}:{mime:"video/mp4",type:"video",ext:"mp4"}}if(this.checkSignature(t,S.WEBM))return{mime:"video/webm",type:"video",ext:"webm"};if(this.checkSignature(t,S.RIFF)&&this.checkSignature(t.subarray(8),S.AVI))return{mime:"video/avi",type:"video",ext:"avi"};if(this.isText(t)){try{let o=new TextDecoder().decode(t),l=JSON.parse(o);if(typeof l=="object"&&l!==null)return{mime:"application/json",type:"json",ext:"json"}}catch{}return{mime:"text/plain",type:"text",ext:"txt"}}return{mime:"application/octet-stream",type:"binary",ext:"bin"}}checkSignature(t,o){if(t.lengththis.download()),l.appendChild(a),l.appendChild(s),l.appendChild(i),this.previewContainer.appendChild(l)}else{let l=document.createElement("div");l.className="empty-view";let a=document.createElement("span");a.className="codicon codicon-file-binary",a.style.fontSize="48px",a.style.opacity="0.5";let s=document.createElement("span");s.style.marginTop="12px",s.textContent="Binary Data";let i=document.createElement("span");i.style.fontSize="12px",i.style.opacity="0.7",i.textContent="Use Hex view to inspect",l.appendChild(a),l.appendChild(s),l.appendChild(i),this.previewContainer.appendChild(l)}}renderHex(t){if(!this.hexContainer)return;let o=16*1e3,l="",a=t.subarray(0,o);for(let s=0;s=32&&p<=126?String.fromCharCode(p):".")}else r.push(" "),d.push(" ");let c=r.slice(0,8).join(" "),m=r.slice(8).join(" "),g=d.join("");l+=`${i} ${c} ${m} |${g}| `}t.length>o&&(l+=` -... (${(t.length-o).toLocaleString()} more bytes not shown)`),this.hexContainer.value=l}formatSize(t){if(t===0)return"0 B";let o=1024,l=["B","KB","MB","GB"],a=Math.floor(Math.log(t)/Math.log(o));return parseFloat((t/Math.pow(o,a)).toFixed(2))+" "+l[a]}};var we;function Oe(){we=new le,document.getElementById("btnCloseCellPreview")?.addEventListener("click",H),document.getElementById("formatJsonBtn")?.addEventListener("click",jt),document.getElementById("compactJsonBtn")?.addEventListener("click",Vt),document.getElementById("wrapTextBtn")?.addEventListener("click",Wt),document.getElementById("openInVsCodeBtn")?.addEventListener("click",be),document.getElementById("btnCancelCellPreview")?.addEventListener("click",H),document.getElementById("cellPreviewSaveBtn")?.addEventListener("click",Ke)}function ze(e,t,o){if(n.selectedTableType!=="table"){u("Views are read-only");return}if(n.editingCellInfo){if(n.editingCellInfo.rowIdx===e&&n.editingCellInfo.colIdx===t)return;se()}let l=n.tableColumns[t];if(!l)return;let a=document.getElementById(`cell-${e}-${t}`);if(!a)return;let s=n.gridData[e],i=P(s,t);if(i instanceof Uint8Array){q(e,t,o);return}if(typeof i=="string"){let d=i.trim();if(d.startsWith("{")&&d.endsWith("}")||d.startsWith("[")&&d.endsWith("]"))try{JSON.parse(d),q(e,t,o);return}catch{}}n.editingCellInfo={rowIdx:e,colIdx:t,rowId:o,columnName:l.name,originalValue:i};let r=i===null?"":String(i);a.innerHTML="",a.classList.add("editing");let c=document.createElement("textarea");c.className="cell-input",c.value=r,c.spellcheck=!1,a.appendChild(c),c.focus(),n.activeCellInput=c,c.addEventListener("keydown",je),c.addEventListener("blur",Ve),c.addEventListener("click",d=>d.stopPropagation()),n.isTransitioningEdit=!0,setTimeout(()=>{n.isTransitioningEdit=!1},100)}function je(e){e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),We()):e.key==="Escape"&&(e.preventDefault(),se())}function Ve(){setTimeout(()=>{n.editingCellInfo&&We()},100)}async function We(){if(n.isSavingCell||!n.editingCellInfo||!n.activeCellInput)return;let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.editingCellInfo,s=n.activeCellInput.value,i=a===null?"":String(a);if(s===i){se(),n.selectedCells=[],n.lastSelectedCell=null,M();return}let r=n.tableColumns[t],c=r&&r.notnull===1,d;s===""?c?d="":d=null:!isNaN(Number(s))&&s.trim()!==""?d=Number(s):d=s;try{n.isSavingCell=!0,u("Saving..."),await y.updateCell(n.selectedTable,te(o),l,d,a),n.gridData[e][t+B()]=d,_e(),Ee(e,t,d),n.selectedCells=[],n.lastSelectedCell=null,M(),u("Saved")}catch(m){console.error("Save failed:",m);let g=m.message||String(m);u(`Save failed: ${g}`)}finally{n.isSavingCell=!1}}function se(){if(!n.editingCellInfo)return;let{rowIdx:e,colIdx:t,originalValue:o}=n.editingCellInfo;_e(),Ee(e,t,o),oe()}function _e(){n.activeCellInput&&(n.activeCellInput.removeEventListener("keydown",je),n.activeCellInput.removeEventListener("blur",Ve),n.activeCellInput=null),n.editingCellInfo=null}async function be(){if(!n.cellPreviewInfo)return;let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.cellPreviewInfo,s=n.tableColumns[t],i=document.getElementById("vscode-env")?.dataset.webviewId||"default";try{u("Opening in VS Code..."),H(),await y.openCellEditor({table:n.selectedTable,name:""},te(o),l,{},{value:a,type:{type:s.type},webviewId:i,rowCount:n.gridData.length}),u("Opened in VS Code")}catch(r){console.error("Failed to open in VS Code:",r),u(`Error: ${r.message}`)}}function q(e,t,o){n.editingCellInfo&&se();let l=n.tableColumns[t];if(!l)return;let a=n.gridData[e];if(!a)return;let s=P(a,t);if(s instanceof Uint8Array){we&&we.inspect(s,o,l.name,e,t);return}n.cellPreviewInfo={rowIdx:e,colIdx:t,rowId:o,columnName:l.name,originalValue:s};let i=document.getElementById("cellPreviewModal"),r=document.getElementById("cellPreviewColumnName"),c=document.getElementById("cellPreviewTypeBadge"),d=document.getElementById("cellPreviewTextarea"),m=document.getElementById("cellPreviewReadonlyBadge"),g=document.getElementById("cellPreviewSaveBtn"),h=document.getElementById("wrapTextBtn");r.textContent=l.name,c.textContent=l.type||"TEXT";let p="";s==null?p="":s instanceof Uint8Array?p="[BLOB: "+Array.from(s).map(b=>b.toString(16).padStart(2,"0")).join(" ")+"]":p=String(s),d.value=p;let f=n.selectedTableType!=="table";d.readOnly=f,f?(d.classList.add("readonly"),m.style.display="inline",g.style.display="none"):(d.classList.remove("readonly"),m.style.display="none",g.style.display="inline-block"),ae(),d.style.whiteSpace=n.cellPreviewWrapEnabled?"pre-wrap":"pre",d.style.overflowX=n.cellPreviewWrapEnabled?"hidden":"auto",h.classList.toggle("active",n.cellPreviewWrapEnabled),i.classList.remove("hidden"),d.focus(),d.oninput=ae,d.onkeydown=b=>{b.key==="Escape"?(b.preventDefault(),H()):b.key==="Enter"&&(b.ctrlKey||b.metaKey)&&(b.preventDefault(),Ke())}}function ae(){let e=document.getElementById("cellPreviewTextarea"),t=document.getElementById("cellPreviewCharCount"),o=e.value.length;t.textContent=`${o.toLocaleString()} character${o!==1?"s":""}`}function H(){document.getElementById("cellPreviewModal").classList.add("hidden"),n.cellPreviewInfo=null}async function Ke(){if(!n.cellPreviewInfo)return;if(n.selectedTableType!=="table"){u("Views are read-only");return}let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.cellPreviewInfo,i=document.getElementById("cellPreviewTextarea").value,r=a===null?"":String(a);if(i===r){H(),n.selectedCells=[],n.lastSelectedCell=null,M();return}let c=n.tableColumns[t],d=c&&c.notnull===1,m;i===""?m=d?"":null:!isNaN(Number(i))&&i.trim()!==""?m=Number(i):m=i;try{u("Saving..."),await y.updateCell(n.selectedTable,te(o),l,m,a),n.gridData[e][t+B()]=m,H(),Ee(e,t,m),n.selectedCells=[],n.lastSelectedCell=null,M(),u("Saved")}catch(g){console.error("Save failed:",g),u(`Save failed: ${g.message}`)}}function jt(){let e=document.getElementById("cellPreviewTextarea");try{let t=JSON.parse(e.value);e.value=JSON.stringify(t,null,2),ae()}catch{u("Content is not valid JSON")}}function Vt(){let e=document.getElementById("cellPreviewTextarea");try{let t=JSON.parse(e.value);e.value=JSON.stringify(t),ae()}catch{u("Content is not valid JSON")}}function Wt(){n.cellPreviewWrapEnabled=!n.cellPreviewWrapEnabled;let e=document.getElementById("cellPreviewTextarea"),t=document.getElementById("wrapTextBtn");e.style.whiteSpace=n.cellPreviewWrapEnabled?"pre-wrap":"pre",e.style.overflowX=n.cellPreviewWrapEnabled?"hidden":"auto",t.classList.toggle("active",n.cellPreviewWrapEnabled)}function Ee(e,t,o){let l=document.getElementById(`cell-${e}-${t}`);if(!l)return;l.classList.remove("editing"),o==null?l.classList.add("null-value"):l.classList.remove("null-value");let a=n.tableColumns[t],s=_(o,a?.type,n.dateFormat,a?.name),i=o!=null&&!(o instanceof Uint8Array);l.textContent="";let r=document.createElement("span");if(r.className="cell-text",r.textContent=s,l.appendChild(r),i){let d=document.createElement("span");d.className="expand-icon codicon codicon-link-external",d.title="View full content",l.appendChild(d)}let c=r.scrollWidth>r.clientWidth;l.classList.toggle("has-overflow",c)}function qe(){clearTimeout(n.filterTimer),n.filterTimer=setTimeout(()=>{n.filterQuery=document.getElementById("filterInput").value,n.currentPageIndex=0,v(),$()},300)}function He(){n.rowsPerPage=parseInt(document.getElementById("pageSizeSelect").value,10),n.currentPageIndex=0,v(),$()}function Ge(){let e=document.getElementById("dateFormatSelect");e&&(n.dateFormat=e.value,z(),$())}function Z(e){e>=0&&el.name===t);if(o!==-1){if((e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),n.selectedRowIds.clear(),e.shiftKey&&n.lastSelectedColumnIndex!==null){e.metaKey||e.ctrlKey||(n.selectedCells=[],n.selectedColumns.clear());let l=Math.min(n.lastSelectedColumnIndex,o),a=Math.max(n.lastSelectedColumnIndex,o),s=new Array;if(n.selectedCells.length>0)for(let i of n.selectedCells)i.colIdx>=l&&i.colIdx<=a&&(s[i.rowIdx]||(s[i.rowIdx]=new Set),s[i.rowIdx].add(i.colIdx));for(let i=l;i<=a;i++){let r=n.tableColumns[i].name;n.selectedColumns.add(r);for(let c=0;c0&&a===l)n.selectedCells=n.selectedCells.filter(i=>i.colIdx!==o),n.selectedColumns.delete(t);else{let i=new Set;for(let r of n.selectedCells)r.colIdx===o&&i.add(r.rowIdx);for(let r=0;r0&&a===l&&n.selectedColumns.size===1&&n.selectedColumns.has(t))n.selectedCells=[],n.selectedColumns.clear(),n.lastSelectedColumnIndex=null;else{n.selectedCells=[],n.selectedColumns.clear();for(let i=0;ii.name===n.resizingColumn);if(l===-1)return;let a=document.querySelector(`th[data-column="${n.resizingColumn}"]`);a&&(a.style.width=`${o}px`,a.style.minWidth=`${o}px`,a.style.maxWidth=`${o}px`);let s=document.querySelectorAll(`.data-row td:nth-child(${l+2})`);for(let i of s)i.style.width=`${o}px`,i.style.minWidth=`${o}px`,i.style.maxWidth=`${o}px`;n.pinnedColumns.has(n.resizingColumn)}function nt(){if(!n.resizingColumn)return;let e=document.querySelector(".resize-handle.resizing");e&&e.classList.remove("resizing"),n.resizingColumn=null,document.removeEventListener("mousemove",tt),document.removeEventListener("mouseup",nt),document.body.style.userSelect="",document.body.style.cursor="",z()}function ot(e,t,o){if(e.stopPropagation(),(e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),e.shiftKey&&n.lastSelectedRowIndex!==null){e.metaKey||e.ctrlKey||n.selectedRowIds.clear();let l=Math.min(n.lastSelectedRowIndex,o),a=Math.max(n.lastSelectedRowIndex,o);for(let s=l;s<=a;s++){let i=T(n.gridData[s],s);n.selectedRowIds.add(i)}}else e.ctrlKey||e.metaKey?(n.selectedRowIds.has(t)?n.selectedRowIds.delete(t):n.selectedRowIds.add(t),n.lastSelectedRowIndex=o):n.selectedRowIds.has(t)&&n.selectedRowIds.size===1?(n.selectedRowIds.delete(t),n.lastSelectedRowIndex=null):(n.selectedRowIds.clear(),n.selectedRowIds.add(t),n.lastSelectedRowIndex=o);M(),R(),O()}function ie(e){if(e.stopPropagation(),n.gridData.length===0)return;n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear();let t=!0;for(let o=0;o=s&&m.rowIdx<=i&&m.colIdx>=r&&m.colIdx<=c&&(d[m.rowIdx]||(d[m.rowIdx]=new Set),d[m.rowIdx].add(m.colIdx));for(let m=s;m<=i;m++){let g=d[m];for(let h=r;h<=c;h++)if(!g||!g.has(h)){let p=T(n.gridData[m],m),f=P(n.gridData[m],h);n.selectedCells.push({rowIdx:m,colIdx:h,rowId:p,value:f})}}}else if(e.metaKey||e.ctrlKey){e.preventDefault(),n.selectedRowIds.clear();let s=n.selectedCells.findIndex(i=>i.rowIdx===t&&i.colIdx===o);s>=0?n.selectedCells.splice(s,1):(n.selectedCells.push({rowIdx:t,colIdx:o,rowId:l,value:a}),n.lastSelectedCell={rowIdx:t,colIdx:o})}else if(e.shiftKey&&n.lastSelectedCell){e.preventDefault(),n.selectedRowIds.clear(),n.selectedCells=[];let s=Math.min(n.lastSelectedCell.rowIdx,t),i=Math.max(n.lastSelectedCell.rowIdx,t),r=Math.min(n.lastSelectedCell.colIdx,o),c=Math.max(n.lastSelectedCell.colIdx,o);for(let d=s;d<=i;d++)for(let m=r;m<=c;m++){let g=T(n.gridData[d],d),h=P(n.gridData[d],m);n.selectedCells.push({rowIdx:d,colIdx:m,rowId:g,value:h})}}else n.selectedRowIds.clear(),n.selectedCells=[{rowIdx:t,colIdx:o,rowId:l,value:a}],n.lastSelectedCell={rowIdx:t,colIdx:o},n.selectedColumns.clear();M(),R(),O()}function at(e,t,o,l){if(n.cellEditBehavior==="vscode"){let a=n.tableColumns[o];if(!a)return;let s=n.gridData[t];if(!s)return;let i=P(s,o);n.cellPreviewInfo={rowIdx:t,colIdx:o,rowId:l,columnName:a.name,originalValue:i},be()}else n.cellEditBehavior==="modal"?q(t,o,l):ze(t,o,l)}function st(){document.getElementById("filterInput")?.addEventListener("keyup",qe),document.getElementById("pageSizeSelect")?.addEventListener("change",He),document.getElementById("dateFormatSelect")?.addEventListener("change",Ge),document.getElementById("btnFirst")?.addEventListener("click",()=>Z(0)),document.getElementById("btnPrev")?.addEventListener("click",()=>Z(n.currentPageIndex-1)),document.getElementById("btnNext")?.addEventListener("click",()=>Z(n.currentPageIndex+1)),document.getElementById("btnLast")?.addEventListener("click",()=>Z(n.totalPageCount-1))}function it(){let e=document.getElementById("gridContainer");e&&(e.addEventListener("mousedown",_t),e.addEventListener("keydown",Kt),e.addEventListener("click",qt),e.addEventListener("dblclick",Jt),e.addEventListener("mouseover",Xt),e.addEventListener("scroll",Yt,{passive:!0}))}function _t(e){if(e.target.classList.contains("resize-handle")){e.stopPropagation();let t=e.target.closest(".header-cell");t&&t.dataset.column&&et(e,t.dataset.column)}}function Kt(e){if(e.target.classList.contains("column-filter")){let t=e.target.dataset.column;t&&Xe(e,t)}}function qt(e){let t=e.target;if(t.closest(".grid-header")){Ht(e,t);return}Gt(e,t)}function Ht(e,t){if(t.closest(".filter-apply-btn")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Ie(l.dataset.column);return}if(t.closest(".header-bottom")||t.closest(".column-filter")){e.stopPropagation();return}if(t.closest(".select-column-icon")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Ye(e,l.dataset.column);return}if(t.closest(".pin-icon")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Ze(e,l.dataset.column);return}if(t.closest(".row-number-header")){ie(e);return}let o=t.closest(".header-top");if(o){let l=o.closest(".header-cell");l&&l.dataset.column&&Je(l.dataset.column);return}}function Gt(e,t){if(t.closest(".pin-icon")){let l=t.closest(".data-row");if(l){let a=l.dataset.rowid,s=Q(a);Qe(e,s)}return}if(t.closest(".expand-icon")){let l=t.closest(".data-cell");if(l){let a=parseInt(l.dataset.rowidx,10),s=parseInt(l.dataset.colidx,10),i=Q(l.closest(".data-row").dataset.rowid);q(a,s,i)}return}if(t.closest(".row-number")){let l=t.closest(".data-row");if(l){let a=Q(l.dataset.rowid),s=parseInt(l.dataset.rowidx,10);ot(e,a,s)}return}let o=t.closest(".data-cell");if(o){let l=parseInt(o.dataset.rowidx,10),a=parseInt(o.dataset.colidx,10),s=o.closest(".data-row"),i=Q(s.dataset.rowid);lt(e,l,a,i);return}}function Jt(e){let t=e.target.closest(".data-cell");if(t&&!t.classList.contains("row-number")){let o=parseInt(t.dataset.rowidx,10),l=parseInt(t.dataset.colidx,10),a=t.closest(".data-row"),s=Q(a.dataset.rowid);at(e,o,l,s)}}function Xt(e){let t=e.target.closest(".data-cell");if(t&&!t.classList.contains("checked-overflow")){let o=t.querySelector(".cell-text");if(o){let l=o.scrollWidth>o.clientWidth;t.classList.toggle("has-overflow",l),t.classList.add("checked-overflow")}}}function Yt(e){let t=e.currentTarget;n.scrollPosition.left=t.scrollLeft,n.scrollPosition.top=t.scrollTop,$()}function Q(e){if(e==null)return e;let t=Number(e);return!isNaN(t)&&e.trim()!==""?t:e}function rt(){document.addEventListener("click",e=>{let t=e.target,o=t.closest(".modal-close, .modal-cancel");if(o){let l=o.dataset.modal;l&&U(l)}t.classList.contains("modal-overlay")&&t.classList.add("hidden")}),document.addEventListener("keydown",e=>{if(e.key==="Escape"){let t=document.querySelector(".modal-overlay:not(.hidden)");t&&(t.classList.add("hidden"),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation())}})}function j(e){let t=document.getElementById(e);if(t){t.classList.remove("hidden");let o=t.querySelector("input, select, textarea, button");o&&o.focus()}}function U(e){let t=document.getElementById(e);t&&t.classList.add("hidden")}function ct(){document.getElementById("btnAddRow")?.addEventListener("click",Zt),document.getElementById("btnDeleteRows")?.addEventListener("click",en),document.getElementById("btnAddColumn")?.addEventListener("click",an),document.getElementById("btnSubmitAddRow")?.addEventListener("click",Qt),document.getElementById("btnSubmitDelete")?.addEventListener("click",re),document.getElementById("btnSubmitCreateTable")?.addEventListener("click",ln),document.getElementById("btnAddColumnDef")?.addEventListener("click",()=>mt()),document.getElementById("columnDefinitions")?.addEventListener("click",e=>{let t=e.target.closest(".btn-remove-col");if(t){let o=t.dataset.colid;on(o)}}),document.getElementById("btnSubmitAddColumn")?.addEventListener("click",sn)}function Zt(){if(!n.selectedTable||n.selectedTableType!=="table")return;let e=document.getElementById("addRowForm");e.replaceChildren(),n.tableColumns.forEach(t=>{let o=t.notnull===1&&!t.isPrimaryKey,l=document.createElement("div");l.className="form-field";let a=document.createElement("label");if(a.textContent=t.name,o){let r=document.createElement("span");r.style.color="var(--error-color)",r.textContent="*",a.appendChild(document.createTextNode(" ")),a.appendChild(r)}let s=document.createElement("span");s.style.opacity="0.5",s.textContent=` (${t.type})`,a.appendChild(document.createTextNode(" ")),a.appendChild(s);let i=document.createElement("input");i.type="text",i.dataset.column=t.name,i.dataset.required=o.toString(),t.isPrimaryKey?(i.placeholder="Auto (Primary Key)",i.disabled=!0):o?i.placeholder="Required":i.placeholder="NULL",l.appendChild(a),l.appendChild(i),e.appendChild(l)}),j("addRowModal")}async function Qt(){let e=document.querySelectorAll("#addRowForm input[data-column]:not([disabled])"),t=[];for(let l of e){let a=l.dataset.column,s=l.value.trim();l.dataset.required==="true"&&(s===""||s.toLowerCase()==="null")?(t.push(a),l.style.borderColor="var(--error-color)"):l.style.borderColor=""}if(t.length>0){u(`Required fields missing: ${t.join(", ")}`);return}let o={};for(let l of e){let a=l.dataset.column,s=l.value.trim();s!==""&&(s.toLowerCase()==="null"?o[a]=null:!isNaN(Number(s))&&s!==""?o[a]=Number(s):o[a]=s)}try{u("Inserting row..."),await y.insertRow(n.selectedTable,o),U("addRowModal"),await v(),u("Row inserted - Ctrl+S to save")}catch(l){console.error("Insert failed:",l),u(`Error: ${l.message}`)}}function en(){if(n.selectedColumns.size>0){let e=Array.from(n.selectedColumns);document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${e.length} column${e.length>1?"s":""} (${e.join(", ")})? This will permanently remove the column${e.length>1?"s":""} and all their data.`}else if(n.selectedRowIds.size>0)document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${n.selectedRowIds.size} row${n.selectedRowIds.size>1?"s":""}?`;else return;j("deleteModal")}async function re(){n.selectedColumns.size>0?await nn():n.selectedRowIds.size>0&&await tn()}async function tn(){if(n.selectedRowIds.size===0)return;let e=Array.from(n.selectedRowIds);try{u("Deleting rows..."),await y.deleteRows(n.selectedTable,e),U("deleteModal"),n.selectedRowIds.clear(),await v(),R(),u(`Deleted ${e.length} row${e.length>1?"s":""} - Ctrl+S to save`)}catch(t){console.error("Delete rows failed:",t),u(`Error: ${t.message}`)}}async function nn(){if(n.selectedColumns.size===0)return;let e=Array.from(n.selectedColumns);try{u("Deleting columns...");let t=await y.deleteColumns(n.selectedTable,e);if(t&&t.cancelled){u("Delete cancelled"),U("deleteModal");return}U("deleteModal"),n.selectedColumns.clear(),n.selectedCells=[],n.lastSelectedCell=null,await V(),await K(),await v(),R(),u(`Deleted ${e.length} column${e.length>1?"s":""} - Ctrl+S to save`)}catch(t){console.error("Delete columns failed:",t),u(`Error: ${t.message}`)}}var dt=0;function ut(){document.getElementById("newTableName").value="",document.getElementById("columnDefinitions").replaceChildren(),dt=0,mt(!0),j("createTableModal")}function mt(e=!1){let t=document.getElementById("columnDefinitions"),o=++dt,l=document.createElement("div");l.className="column-def-row",l.id=`colDef_${o}`,Object.assign(l.style,{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center"});let a=document.createElement("input");a.type="text",a.placeholder="Column name",a.className="col-name",a.style.flex="2",e&&(a.value="id"),l.appendChild(a);let s=document.createElement("select");s.className="col-type",s.style.flex="1",["INTEGER","TEXT","REAL","BLOB","NUMERIC"].forEach(h=>{let p=document.createElement("option");p.value=h,p.textContent=h,e&&h==="INTEGER"&&(p.selected=!0),!e&&h==="TEXT"&&(p.selected=!0),s.appendChild(p)}),l.appendChild(s);let i=document.createElement("label");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let r=document.createElement("input");r.type="checkbox",r.className="col-pk",r.style.margin="0",e&&(r.checked=!0),i.appendChild(r),i.appendChild(document.createTextNode(" PK")),l.appendChild(i);let c=document.createElement("label");Object.assign(c.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let d=document.createElement("input");d.type="checkbox",d.className="col-nn",d.style.margin="0",c.appendChild(d),c.appendChild(document.createTextNode(" NN")),l.appendChild(c);let m=document.createElement("button");m.className="icon-button btn-remove-col",m.dataset.colid=o.toString(),m.title="Remove",e&&(m.disabled=!0);let g=document.createElement("span");g.className="codicon codicon-close",m.appendChild(g),l.appendChild(m),t.appendChild(l)}function on(e){let t=document.getElementById(`colDef_${e}`);t&&t.remove()}async function ln(){let e=document.getElementById("newTableName").value.trim();if(!e){u("Error: Table name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid table name");return}let t=[],o=document.querySelectorAll(".column-def-row");for(let l of o){let a=l.querySelector(".col-name").value.trim(),s=l.querySelector(".col-type").value,i=l.querySelector(".col-pk").checked,r=l.querySelector(".col-nn").checked;a&&t.push({name:a,type:s,primaryKey:i,notNull:r})}if(t.length===0){u("Error: At least one column is required");return}try{u("Creating table..."),await y.createTable(e,t),U("createTableModal"),await V(),u(`Table "${e}" created - Ctrl+S to save`)}catch(l){console.error("Create table failed:",l),u(`Error: ${l.message}`)}}function an(){!n.selectedTable||n.selectedTableType!=="table"||(document.getElementById("newColumnName").value="",document.getElementById("newColumnType").value="TEXT",document.getElementById("newColumnDefault").value="",j("addColumnModal"))}async function sn(){let e=document.getElementById("newColumnName").value.trim(),t=document.getElementById("newColumnType").value,o=document.getElementById("newColumnDefault").value.trim();if(!e){u("Error: Column name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid column name");return}try{u("Adding column..."),await y.addColumn(n.selectedTable,e,t,o),U("addColumnModal"),await K(),await v(),u(`Column "${e}" added - Ctrl+S to save`)}catch(l){console.error("Add column failed:",l),u(`Error: ${l.message}`)}}function pt(){let e=document.getElementById("pragmaSettingsContainer");e&&e.addEventListener("change",t=>{let o=t.target;if(o.matches(".setting-extension")){let l=o.dataset.key,a=o.type==="checkbox"?o.checked:o.value;cn(l,a)}else if(o.matches(".setting-pragma")){let l=o.dataset.name,a=o.dataset.type,s=o.value;a==="number"?s=Number(s):a==="bool"&&(s=s==="true"?1:0),dn(l,s)}})}async function ft(){let e=document.getElementById("settingsModal");e&&(e.classList.remove("hidden"),await ve())}async function ve(){let e=document.getElementById("pragmaSettingsContainer");e.textContent="Loading settings...";try{let[t,o]=await Promise.all([y.getPragmas(),y.getExtensionSettings()]);rn(t,o)}catch(t){console.error("Failed to load settings:",t),e.textContent=`Error loading settings: ${t.message}`,e.style.color="var(--error-color)"}}function rn(e,t){let o=document.getElementById("pragmaSettingsContainer");if(!o)return;let l=(x,C)=>x.map(k=>{let L=String(k),D=String(C).toUpperCase()===L.toUpperCase(),N=document.createElement("option");return N.value=L,N.selected=D,N.textContent=L,N});o.replaceChildren();let a=x=>{let C=document.createElement("div");C.className="setting-section-title",Object.assign(C.style,{fontWeight:"600",marginBottom:"8px",paddingBottom:"4px",borderBottom:"1px solid var(--border-color)"}),C.textContent=x,o.appendChild(C)},s=(x,C,k)=>{let L=document.createElement("div");L.className="form-field";let w=document.createElement("label");if(C.type==="checkbox"?(Object.assign(w.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"}),C.style.margin="0",w.appendChild(C),w.appendChild(document.createTextNode(x)),L.appendChild(w)):(w.textContent=x,L.appendChild(w),L.appendChild(C)),k){let D=document.createElement("div");D.className="setting-desc",D.textContent=k,L.appendChild(D)}o.appendChild(L)};if(o.children.length>0){let x=document.createElement("div");x.style.height="16px",o.appendChild(x)}a("Extension Settings");let i=document.createElement("input");i.type="checkbox",i.className="setting-extension",i.dataset.key="autoCommit",i.checked=!!t.autoCommit,s("Auto-Commit Changes",i,"Automatically save changes to disk immediately. If disabled, you must save manually (Ctrl+S).");let r=document.createElement("select");r.className="setting-extension",r.dataset.key="doubleClickBehavior",l(["inline","modal","vscode"],t.cellEditBehavior).forEach(x=>r.appendChild(x)),s("Double Click Behavior",r,"Action when double-clicking a cell");let c=document.createElement("div");c.style.height="16px",o.appendChild(c),a("SQLite Settings (Pragmas)");let d=document.createElement("select");d.className="setting-pragma",d.dataset.name="journal_mode",l(["DELETE","TRUNCATE","PERSIST","MEMORY","WAL","OFF"],e.journal_mode).forEach(x=>d.appendChild(x)),s("Journal Mode",d,"Database journaling mode (WAL is recommended for concurrency)");let m=document.createElement("select");m.className="setting-pragma",m.dataset.name="foreign_keys",m.dataset.type="bool";let g=document.createElement("option");g.value="true",g.textContent="ON";let h=document.createElement("option");h.value="false",h.textContent="OFF",Number(e.foreign_keys)===1?g.selected=!0:h.selected=!0,m.appendChild(g),m.appendChild(h),s("Foreign Keys",m,"Enforce foreign key constraints");let p=document.createElement("select");p.className="setting-pragma",p.dataset.name="synchronous",p.dataset.type="number",[{v:0,t:"OFF (0)"},{v:1,t:"NORMAL (1)"},{v:2,t:"FULL (2)"},{v:3,t:"EXTRA (3)"}].forEach(x=>{let C=document.createElement("option");C.value=x.v,C.textContent=x.t,Number(e.synchronous)===x.v&&(C.selected=!0),p.appendChild(C)}),s("Synchronous",p,"Disk synchronization safety level");let f=document.createElement("select");f.className="setting-pragma",f.dataset.name="locking_mode",l(["NORMAL","EXCLUSIVE"],e.locking_mode).forEach(x=>f.appendChild(x)),s("Locking Mode",f,"");let b=document.createElement("select");b.className="setting-pragma",b.dataset.name="auto_vacuum",b.dataset.type="number",[{v:0,t:"NONE (0)"},{v:1,t:"FULL (1)"},{v:2,t:"INCREMENTAL (2)"}].forEach(x=>{let C=document.createElement("option");C.value=x.v,C.textContent=x.t,Number(e.auto_vacuum)===x.v&&(C.selected=!0),b.appendChild(C)}),s("Auto Vacuum",b,"");let I=document.createElement("input");I.type="number",I.className="setting-pragma",I.dataset.name="cache_size",I.dataset.type="number",I.value=e.cache_size,s("Cache Size",I,"Number of pages (positive) or kilobytes (negative)")}async function cn(e,t){try{await y.updateExtensionSetting(e,t),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await ve()}}async function dn(e,t){try{u(`Updating ${e}...`),await y.setPragma(e,t),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await ve()}}function ht(e,t){let o=new Map;for(let l of e){if(!o.has(l.colIdx)){let a=t[l.colIdx];o.set(l.colIdx,{name:a.name,type:a.type,values:new Set})}o.get(l.colIdx).values.add(l.value)}return o}function gt(e){let t=Array.from(e);if(t.length>1)return"(mixed values)";let o=t[0];return o===null?"NULL":o instanceof Uint8Array?"[BLOB]":String(o)}function yt(e,t,o){let l=[];for(let a of e){let s=t.get(a.colIdx);if(!s)continue;let i=s.dataset.isnull==="true",r=s.dataset.ispatch==="true",c=s.value;if(c===""&&!i)continue;let d=o[a.colIdx],m=c,g="set";i?m=null:r?g="json_patch":(d.type==="INTEGER"||d.type==="REAL"||d.type==="NUMERIC")&&!isNaN(Number(c))&&c.trim()!==""&&(m=Number(c)),l.push({rowId:a.rowId,column:d.name,value:m,originalValue:a.value,operation:g,rowIdx:a.rowIdx,colIdx:a.colIdx})}return l}function xt(){let e=document.getElementById("sidebarPanel");if(!e)return;let t=document.getElementById("sidebarFilterInput");t&&t.addEventListener("input",()=>{n.sidebarFilter=t.value,Be()}),e.addEventListener("click",o=>{let l=o.target;if(l.closest("#btnOpenSettings")){ft();return}if(l.closest("#btnOpenCreateTable")){o.stopPropagation(),ut();return}if(l.closest("#btnReload")){yn();return}if(l.closest("#btnApplyBatchUpdate")){mn();return}let a=l.closest(".list-item");if(a){let c=a.dataset.name,d=a.dataset.type;if(c&&d){gn(c,d);return}}let s=l.closest(".section-title");if(s){if(l.closest(".icon-button")||s.id==="btnOpenSettings")return;let c=s.dataset.section;c&&hn(c)}let i=l.closest(".btn-batch-null");if(i){let c=i.closest(".batch-field");if(c){let d=parseInt(c.dataset.colidx,10);pn(d)}return}let r=l.closest(".btn-batch-patch");if(r){let c=r.closest(".batch-field");if(c){let d=parseInt(c.dataset.colidx,10);fn(d,r)}return}})}async function V(){if(n.isDbConnected)try{let e=await y.fetchSchema();n.schemaCache.tables=(e.tables||[]).map(t=>({name:t.identifier})),n.schemaCache.views=(e.views||[]).map(t=>({name:t.identifier})),n.schemaCache.indexes=(e.indexes||[]).map(t=>({name:t.identifier,table:t.parentTable})),Be()}catch(e){console.error("Error loading schema:",e),u("Error loading schema")}}function Se(e,t){return t?e.filter(o=>o.name.toLowerCase().includes(t)):e}function Te(e,t,o,l){let a=document.getElementById(e);a&&(a.textContent=l?`${t}/${o}`:o)}function Ct(e,t,o,l,a){let s=document.getElementById(e);if(!s)return;if(s.replaceChildren(),t.length===0){let r=document.createElement("li");r.className="list-item",r.style.opacity="0.5",r.textContent=a,s.appendChild(r);return}let i=document.createDocumentFragment();t.forEach(r=>{let c=document.createElement("li");c.className="list-item",n.selectedTable===r.name&&n.selectedTableType===o&&c.classList.add("selected"),c.dataset.name=r.name,o&&(c.dataset.type=o),c.title=r.name;let d=document.createElement("span");d.className=`item-icon codicon ${l}`,c.appendChild(d);let m=document.createElement("span");m.className="item-name",m.textContent=r.name,c.appendChild(m),i.appendChild(c)}),s.appendChild(i)}function un(e,t,o){let l=document.getElementById(e);if(!l)return;if(l.replaceChildren(),t.length===0){let s=document.createElement("li");s.className="list-item",s.style.opacity="0.5",s.textContent=o,l.appendChild(s);return}let a=document.createDocumentFragment();t.forEach(s=>{let i=document.createElement("li");i.className="list-item",i.title=`${s.name} on ${s.table}`;let r=document.createElement("span");r.className="item-icon codicon codicon-list-selection",i.appendChild(r);let c=document.createElement("div");c.className="item-content";let d=document.createElement("span");d.className="item-name",d.textContent=s.name,c.appendChild(d);let m=document.createElement("span");m.className="item-detail",m.textContent=s.table,c.appendChild(m),i.appendChild(c),a.appendChild(i)}),l.appendChild(a)}function Be(){let e=n.sidebarFilter.toLowerCase(),t=e.length>0,o=Se(n.schemaCache.tables,e),l=Se(n.schemaCache.views,e),a=Se(n.schemaCache.indexes,e);Te("tablesBadge",o.length,n.schemaCache.tables.length,t),Te("viewsBadge",l.length,n.schemaCache.views.length,t),Te("indexesBadge",a.length,n.schemaCache.indexes.length,t),Ct("tablesList",o,"table","codicon-table",e?"No matching tables":"No tables"),Ct("viewsList",l,"view","codicon-eye",e?"No matching views":"No views"),un("indexesList",a,e?"No matching indexes":"No indexes")}function O(){let e=document.getElementById("batchUpdateSectionTitle"),t=document.getElementById("batchUpdateList"),o=document.getElementById("batchUpdateCount"),l=document.getElementById("batchUpdateFields");if(!e||!t||!o||!l)return;let a=n.selectedCells.length;if(a===0){e.classList.add("hidden"),t.classList.add("hidden");return}e.classList.remove("hidden"),t.classList.remove("hidden"),e.classList.remove("collapsed"),o.textContent=a;let s=ht(n.selectedCells,n.tableColumns);l.replaceChildren();for(let[i,r]of s){let c=gt(r.values),d=document.createElement("div");d.className="form-field batch-field",d.dataset.colidx=i,d.style.marginBottom="8px";let m=document.createElement("label");m.style.fontSize="11px",m.style.color="var(--text-secondary)";let g=document.createTextNode(r.name+" ");m.appendChild(g);let h=document.createElement("span");h.style.opacity="0.7",h.textContent=r.type||"",m.appendChild(h),d.appendChild(m);let p=document.createElement("div");p.style.display="flex",p.style.gap="4px";let f=document.createElement("input");f.type="text",f.className="batch-input",f.placeholder=c,f.dataset.colidx=i,f.style.flex="1",f.style.minWidth="0",p.appendChild(f);let b=document.createElement("button");b.className="btn-secondary btn-batch-null",b.style.padding="2px 6px",b.title="Set to NULL",b.textContent="NULL",p.appendChild(b);let I=document.createElement("button");I.className="btn-secondary btn-batch-patch",I.style.padding="2px 6px",I.title="JSON Patch",I.textContent="{}",p.appendChild(I),d.appendChild(p),l.appendChild(d)}}async function mn(){if(n.selectedCells.length===0)return;let e=document.querySelectorAll(".batch-input"),t=new Map;for(let l of e){let a=parseInt(l.dataset.colidx,10);if(t.set(a,l),l.dataset.ispatch==="true")try{JSON.parse(l.value)}catch{let i=n.tableColumns[a];u(`Invalid JSON for patch in ${i.name}`);return}}let o=yt(n.selectedCells,t,n.tableColumns);if(o.length===0){u("No values entered for batch update");return}try{u(`Updating ${o.length} cells...`);let l=`Batch update ${o.length} cells`,a=o.map(r=>({rowId:r.rowId,column:r.column,value:r.value,originalValue:r.originalValue,operation:r.operation}));if(await y.updateCellBatch(n.selectedTable,a,l),!o.some(r=>r.operation==="json_patch"))for(let r of o)n.gridData[r.rowIdx][r.colIdx+B()]=r.value;await v(!1);let i=[];for(let r of n.selectedCells){let c=n.gridData[r.rowIdx][r.colIdx+B()];i.push({...r,value:c})}n.selectedCells=i,O(),u("Batch update completed")}catch(l){console.error("Batch update failed:",l),u(`Batch update failed: ${l.message}`)}}function pn(e){let t=document.querySelector(`.batch-input[data-colidx="${e}"]`),o=document.querySelector(`.batch-field[data-colidx="${e}"] .btn-batch-patch`);t&&(t.value="",t.placeholder="SET TO NULL",t.dataset.isnull="true",t.dataset.ispatch="false",t.style.fontStyle="italic",o&&(o.style.background="",o.style.color=""))}function fn(e,t){let o=document.querySelector(`.batch-input[data-colidx="${e}"]`);o&&(o.dataset.ispatch==="true"?(o.dataset.ispatch="false",o.placeholder="(mixed values)",t.style.background="",t.style.color=""):(o.dataset.ispatch="true",o.dataset.isnull="false",o.placeholder='JSON Patch (e.g. {"a": 1})',o.style.fontStyle="normal",t.style.background="var(--accent-color)",t.style.color="white"))}function hn(e){let t=document.getElementById(`${e}List`),o=document.querySelector(`.section-title[data-section="${e}"]`);t&&o&&(t.classList.toggle("hidden"),o.classList.toggle("collapsed"))}async function gn(e,t){n.selectedTable=e,n.selectedTableType=t,n.currentPageIndex=0,n.sortedColumn=null,n.sortAscending=!0,n.filterQuery="",n.columnFilters={},n.selectedRowIds.clear(),n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),n.pinnedColumns.clear(),n.pinnedRowIds.clear(),n.columnWidths={},n.scrollPosition={top:0,left:0},Be();let o=document.getElementById("tableNameLabel");o&&(o.textContent=e);let l=document.getElementById("filterInput");l&&(l.value=""),await K(),await v(!0,!1),$()}async function yn(){if(n.isDbConnected)try{u("Reloading..."),await y.refreshFile(),await V(),n.selectedTable&&(await K(),await v()),u("Reloaded")}catch(e){console.error("Reload failed:",e),u(`Reload failed: ${e.message}`)}}function wt(){document.getElementById("btnExport")?.addEventListener("click",Cn),document.getElementById("btnSubmitExport")?.addEventListener("click",xn),document.getElementById("exportFormat")?.addEventListener("change",bt)}function Cn(){if(!n.selectedTable)return;let e=document.getElementById("exportFormat");e&&(e.value="csv");let t=document.getElementById("exportColumns");t&&(t.replaceChildren(),n.tableColumns.forEach(o=>{let l=document.createElement("div"),a=document.createElement("label");Object.assign(a.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let s=document.createElement("input");s.type="checkbox",s.className="export-col-check",s.value=o.name,s.checked=!0,s.style.margin="0",a.appendChild(s),a.appendChild(document.createTextNode(o.name)),t.appendChild(a)})),bt(),j("exportModal")}function bt(){let e=document.getElementById("exportFormat").value,t=document.getElementById("exportOptions");if(t.replaceChildren(),e==="csv"||e==="excel"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportHeader",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Headers")),t.appendChild(o)}else if(e==="sql"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportTableName",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Table Name")),t.appendChild(o)}}async function xn(){let e=document.getElementById("exportFormat").value,t=document.querySelectorAll(".export-col-check:checked"),o=Array.from(t).map(a=>a.value);if(o.length===0){u("Error: Select at least one column");return}let l={};if(e==="csv"||e==="excel"?l.header=document.getElementById("exportHeader")?.checked??!0:e==="sql"&&(l.includeTableName=document.getElementById("exportTableName")?.checked??!0),n.selectedTableType==="table"){let a=Array.from(n.selectedRowIds);a.length>0&&(l.rowIds=a)}try{u("Exporting..."),U("exportModal"),await y.exportTable({table:n.selectedTable},o,null,null,{format:e,...l}),u("Export initiated")}catch(a){console.error("Export failed:",a),u(`Export failed: ${a.message}`)}}async function Et(){if(n.selectedCells.length!==0)try{let e;if(n.selectedCells.length===1){let t=n.selectedCells[0].value;t==null?e="":t instanceof Uint8Array?e="[BLOB]":e=String(t)}else{let t=[...new Set(n.selectedCells.map(s=>s.rowIdx))].sort((s,i)=>s-i),o=[...new Set(n.selectedCells.map(s=>s.colIdx))].sort((s,i)=>s-i),l=new Map;for(let s of n.selectedCells)l.set(`${s.rowIdx},${s.colIdx}`,s.value);let a=[];for(let s of t){let i=[];for(let r of o){let c=`${s},${r}`,d=l.has(c)?l.get(c):"";d==null?d="":d instanceof Uint8Array?d="[BLOB]":(d=String(d),d=d.replace(/\t/g," ").replace(/\n/g," ")),i.push(d)}a.push(i.join(" "))}e=a.join(` -`)}await navigator.clipboard.writeText(e),u(`Copied ${n.selectedCells.length} cell${n.selectedCells.length>1?"s":""}`)}catch(e){console.error("Copy failed:",e),u("Copy failed: "+e.message)}}async function It(){if(n.selectedRowIds.size!==0)try{let e=[];for(let l=0;lc==null?"":c instanceof Uint8Array?"[BLOB]":String(c));e.push(r.join(" "))}}let o=[n.tableColumns.map(l=>l.name).join(" "),...e].join(` -`);await navigator.clipboard.writeText(o),u(`Copied ${e.length} row${e.length>1?"s":""} to clipboard`)}catch(e){console.error("Copy failed:",e),u("Copy failed: "+e.message)}}async function vt(){if(n.selectedCells.length!==0){if(n.selectedTableType!=="table"){u("Views are read-only");return}try{u("Clearing cells...");let e=[];for(let o of n.selectedCells){let l=n.tableColumns[o.colIdx];if(!l)continue;let s=l.notnull===1?"":null;e.push({rowId:o.rowId,column:l.name,value:s,originalValue:o.value,rowIdx:o.rowIdx,colIdx:o.colIdx})}let t=`Clear ${e.length} cell${e.length>1?"s":""}`;await y.updateCellBatch(n.selectedTable,e,t);for(let o of e)n.gridData[o.rowIdx][o.colIdx+B()]=o.value;n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),await v(),R(),u(`${t} - Ctrl+S to save`)}catch(e){console.error("Clear cells failed:",e),u(`Clear failed: ${e.message}`)}}}var ce=50*1024*1024,Le=!1;function St(){let e=document.getElementById("gridContainer");if(!e){console.error("gridContainer not found");return}document.addEventListener("dragover",t=>t.preventDefault()),document.addEventListener("drop",t=>t.preventDefault()),e.addEventListener("dragover",wn),e.addEventListener("dragleave",bn),e.addEventListener("drop",En)}var F=null;function wn(e){e.preventDefault(),e.dataTransfer.dropEffect="copy";let t=e.target.closest(".data-cell");t&&!t.classList.contains("row-number")?(F&&F!==t&&F.classList.remove("drag-over"),t.classList.add("drag-over"),F=t):F&&(F.classList.remove("drag-over"),F=null)}function bn(e){e.target}async function En(e){e.preventDefault(),F&&(F.classList.remove("drag-over"),F=null);let t=e.target.closest(".data-cell");if(!t||t.classList.contains("row-number"))return;if(e.dataTransfer.files.length>0){let l=e.dataTransfer.files[0];await In(t,l.name,l);return}let o=e.dataTransfer.getData("text/uri-list");if(o){let l=o.split(/\r?\n/);if(l.length>0&&l[0]){let a=l[0],s="unknown_file";try{let i=a.split("/");s=decodeURIComponent(i[i.length-1])}catch(i){console.warn("Failed to parse name from URI",i)}await vn(t,s,a);return}}}async function In(e,t,o){if(o.size>ce){let l=(o.size/1048576).toFixed(1),a=(ce/(1024*1024)).toFixed(0);u(`File too large (${l}MB). Maximum is ${a}MB.`);return}try{u(`Reading ${t}...`);let l=await Sn(o),a=new Uint8Array(l);await Tt(e,t,a)}catch(l){console.error("File read failed:",l),u(`File read failed: ${l.message}`)}}async function vn(e,t,o){try{u(`Fetching ${t}...`);let l=await y.readWorkspaceFileUri(o),a;if(l instanceof Uint8Array)a=l;else if(l&&l.type==="Buffer"&&Array.isArray(l.data))a=new Uint8Array(l.data);else if(l&&typeof l=="object"&&Object.keys(l).some(s=>!isNaN(s)))a=new Uint8Array(Object.values(l));else throw console.error("Unknown data format from backend:",l),new Error("Received invalid data format from backend");await Tt(e,t,a)}catch(l){console.error("URI upload failed:",l),u(`Upload failed: ${l.message}`)}}async function Tt(e,t,o){if(Le){u("Upload already in progress...");return}if(o.byteLength>ce){let c=(o.byteLength/1048576).toFixed(1),d=(ce/(1024*1024)).toFixed(0);u(`File too large (${c}MB). Maximum is ${d}MB.`);return}let l=parseInt(e.dataset.rowidx,10),a=parseInt(e.dataset.colidx,10);if(!n.gridData)return;let s=n.gridData[l];if(!s)return;let i=T(s,l),r=n.tableColumns[a];if(n.selectedTableType!=="table"){u("Cannot upload to a view");return}Le=!0,n.isLoadingData=!0;try{u(`Uploading ${t} (${Tn(o.byteLength)})...`);let c=s[a+B()];await y.updateCell(n.selectedTable,i,r.name,o,c),n.gridData[l][a+B()]=o,Bn(e,o),u(`Uploaded ${t}`)}catch(c){console.error("Upload failed:",c);let d=c.message||String(c);d.includes("timeout")&&(d="Upload timed out. Try a smaller file."),u(`Upload failed: ${d}`)}finally{Le=!1,n.isLoadingData=!1}}function Sn(e){return new Promise((t,o)=>{let l=new FileReader;l.onload=()=>t(l.result),l.onerror=()=>o(l.error),l.readAsArrayBuffer(e)})}function Tn(e){if(e===0)return"0 B";let t=1024,o=["B","KB","MB","GB"],l=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,l)).toFixed(2))+" "+o[l]}function Bn(e,t){let o=_(t);e.textContent="";let l=document.createElement("span");l.className="cell-text",l.textContent=o,e.appendChild(l);let a=document.createElement("span");a.className="expand-icon codicon codicon-link-external",a.title="View full content",e.appendChild(a),e.classList.remove("null-value")}var Bt={async refreshContent(e){return n.isDbConnected&&(await V(),!(n.schemaCache.tables.some(o=>o.name===n.selectedTable)||n.schemaCache.views.some(o=>o.name===n.selectedTable))&&n.selectedTable?(n.selectedTable=null,n.selectedTableType=null,document.getElementById("tableNameLabel").textContent="No table selected",xe()):n.selectedTable&&await v(!1)),{success:!0}},async updateColorScheme(e){return document.documentElement.style.colorScheme=e,{success:!0}},async updateCellEditBehavior(e){return n.cellEditBehavior=e,{success:!0}}};function Ln(){window.addEventListener("message",e=>{let t=e.data;if(t&&t.kind==="invoke"){let{correlationId:l,methodName:a,parameters:s}=t,i=Bt[a];typeof i=="function"?Promise.resolve(i.apply(Bt,s||[])).then(r=>{Ae(l,r)}).catch(r=>{ye(l,r instanceof Error?r.message:String(r))}):ye(l,`Unknown method: ${a}`);return}if(!t||t.channel!=="rpc")return;let o=t.content;o&&o.kind==="response"&&ke(o)})}Ln();async function Rn(){try{xt(),ct(),wt(),rt(),pt(),Oe(),st(),it(),Me(),St();let e=document.getElementById("openInVsCodeBtn");e&&(e.style.display="none"),u("Connecting to database...");let t=await y.initialize();n.isDbConnected=!0,await y.ping(),await V(),u("Ready"),xe(),document.addEventListener("keydown",async o=>{if(o.key==="Escape"&&!n.editingCellInfo&&!document.querySelector(".modal-overlay:not(.hidden)")&&oe(),(o.metaKey||o.ctrlKey)&&o.key==="c"){if(n.editingCellInfo||document.activeElement.tagName==="INPUT")return;n.selectedCells.length>0?(o.preventDefault(),await Et()):n.selectedRowIds.size>0&&(o.preventDefault(),await It())}if((o.metaKey||o.ctrlKey)&&o.key==="a"){if(n.editingCellInfo||document.activeElement.tagName==="INPUT")return;n.selectedTable&&(o.preventDefault(),ie(o))}if((o.metaKey||o.ctrlKey)&&(o.key==="Delete"||o.key==="Backspace")){if(n.editingCellInfo||document.activeElement.tagName==="INPUT"||document.activeElement.tagName==="TEXTAREA")return;n.selectedTable&&n.selectedTableType==="table"&&(o.preventDefault(),n.selectedColumns.size>0?await re():n.selectedRowIds.size>0?await re():n.selectedCells.length>0&&await vt())}})}catch(e){console.error("Init error:",e),ne(e.message)}}Rn();})(); +... (${(t.length-o).toLocaleString()} more bytes not shown)`),this.hexContainer.value=l}formatSize(t){if(t===0)return"0 B";let o=1024,l=["B","KB","MB","GB"],a=Math.floor(Math.log(t)/Math.log(o));return parseFloat((t/Math.pow(o,a)).toFixed(2))+" "+l[a]}};var we;function Oe(){we=new le,document.getElementById("btnCloseCellPreview")?.addEventListener("click",H),document.getElementById("formatJsonBtn")?.addEventListener("click",jt),document.getElementById("compactJsonBtn")?.addEventListener("click",Vt),document.getElementById("wrapTextBtn")?.addEventListener("click",Wt),document.getElementById("openInVsCodeBtn")?.addEventListener("click",be),document.getElementById("btnCancelCellPreview")?.addEventListener("click",H),document.getElementById("cellPreviewSaveBtn")?.addEventListener("click",Ke)}function ze(e,t,o){if(n.selectedTableType!=="table"){u("Views are read-only");return}if(n.editingCellInfo){if(n.editingCellInfo.rowIdx===e&&n.editingCellInfo.colIdx===t)return;se()}let l=n.tableColumns[t];if(!l)return;let a=document.getElementById(`cell-${e}-${t}`);if(!a)return;let s=n.gridData[e],i=P(s,t);if(i instanceof Uint8Array){q(e,t,o);return}if(typeof i=="string"){let c=i.trim();if(c.startsWith("{")&&c.endsWith("}")||c.startsWith("[")&&c.endsWith("]"))try{JSON.parse(c),q(e,t,o);return}catch{}}n.editingCellInfo={rowIdx:e,colIdx:t,rowId:o,columnName:l.name,originalValue:i};let r=i===null?"":String(i);a.innerHTML="",a.classList.add("editing");let d=document.createElement("textarea");d.className="cell-input",d.value=r,d.spellcheck=!1,a.appendChild(d),d.focus(),n.activeCellInput=d,d.addEventListener("keydown",je),d.addEventListener("blur",Ve),d.addEventListener("click",c=>c.stopPropagation()),n.isTransitioningEdit=!0,setTimeout(()=>{n.isTransitioningEdit=!1},100)}function je(e){e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),We()):e.key==="Escape"&&(e.preventDefault(),se())}function Ve(){setTimeout(()=>{n.editingCellInfo&&We()},100)}async function We(){if(n.isSavingCell||!n.editingCellInfo||!n.activeCellInput)return;let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.editingCellInfo,s=n.activeCellInput.value,i=a===null?"":String(a);if(s===i){se(),n.selectedCells=[],n.lastSelectedCell=null,M();return}let r=n.tableColumns[t],d=r&&r.notnull===1,c;s===""?d?c="":c=null:!isNaN(Number(s))&&s.trim()!==""?c=Number(s):c=s;try{n.isSavingCell=!0,u("Saving..."),await y.updateCell(n.selectedTable,te(o),l,c,a),n.gridData[e][t+B()]=c,_e(),Ee(e,t,c),n.selectedCells=[],n.lastSelectedCell=null,M(),u("Saved")}catch(m){console.error("Save failed:",m);let g=m.message||String(m);u(`Save failed: ${g}`)}finally{n.isSavingCell=!1}}function se(){if(!n.editingCellInfo)return;let{rowIdx:e,colIdx:t,originalValue:o}=n.editingCellInfo;_e(),Ee(e,t,o),oe()}function _e(){n.activeCellInput&&(n.activeCellInput.removeEventListener("keydown",je),n.activeCellInput.removeEventListener("blur",Ve),n.activeCellInput=null),n.editingCellInfo=null}async function be(){if(!n.cellPreviewInfo)return;let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.cellPreviewInfo,s=n.tableColumns[t],i=document.getElementById("vscode-env")?.dataset.webviewId||"default";try{u("Opening in VS Code..."),H(),await y.openCellEditor({table:n.selectedTable,name:""},te(o),l,{},{value:a,type:{type:s.type},webviewId:i,rowCount:n.gridData.length}),u("Opened in VS Code")}catch(r){console.error("Failed to open in VS Code:",r),u(`Error: ${r.message}`)}}function q(e,t,o){n.editingCellInfo&&se();let l=n.tableColumns[t];if(!l)return;let a=n.gridData[e];if(!a)return;let s=P(a,t);if(s instanceof Uint8Array){we&&we.inspect(s,o,l.name,e,t);return}n.cellPreviewInfo={rowIdx:e,colIdx:t,rowId:o,columnName:l.name,originalValue:s};let i=document.getElementById("cellPreviewModal"),r=document.getElementById("cellPreviewColumnName"),d=document.getElementById("cellPreviewTypeBadge"),c=document.getElementById("cellPreviewTextarea"),m=document.getElementById("cellPreviewReadonlyBadge"),g=document.getElementById("cellPreviewSaveBtn"),f=document.getElementById("wrapTextBtn");r.textContent=l.name,d.textContent=l.type||"TEXT";let p="";s==null?p="":s instanceof Uint8Array?p="[BLOB: "+Array.from(s).map(b=>b.toString(16).padStart(2,"0")).join(" ")+"]":p=String(s),c.value=p;let h=n.selectedTableType!=="table";c.readOnly=h,h?(c.classList.add("readonly"),m.style.display="inline",g.style.display="none"):(c.classList.remove("readonly"),m.style.display="none",g.style.display="inline-block"),ae(),c.style.whiteSpace=n.cellPreviewWrapEnabled?"pre-wrap":"pre",c.style.overflowX=n.cellPreviewWrapEnabled?"hidden":"auto",f.classList.toggle("active",n.cellPreviewWrapEnabled),i.classList.remove("hidden"),c.focus(),c.oninput=ae,c.onkeydown=b=>{b.key==="Escape"?(b.preventDefault(),H()):b.key==="Enter"&&(b.ctrlKey||b.metaKey)&&(b.preventDefault(),Ke())}}function ae(){let e=document.getElementById("cellPreviewTextarea"),t=document.getElementById("cellPreviewCharCount"),o=e.value.length;t.textContent=`${o.toLocaleString()} character${o!==1?"s":""}`}function H(){document.getElementById("cellPreviewModal").classList.add("hidden"),n.cellPreviewInfo=null}async function Ke(){if(!n.cellPreviewInfo)return;if(n.selectedTableType!=="table"){u("Views are read-only");return}let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.cellPreviewInfo,i=document.getElementById("cellPreviewTextarea").value,r=a===null?"":String(a);if(i===r){H(),n.selectedCells=[],n.lastSelectedCell=null,M();return}let d=n.tableColumns[t],c=d&&d.notnull===1,m;i===""?m=c?"":null:!isNaN(Number(i))&&i.trim()!==""?m=Number(i):m=i;try{u("Saving..."),await y.updateCell(n.selectedTable,te(o),l,m,a),n.gridData[e][t+B()]=m,H(),Ee(e,t,m),n.selectedCells=[],n.lastSelectedCell=null,M(),u("Saved")}catch(g){console.error("Save failed:",g),u(`Save failed: ${g.message}`)}}function jt(){let e=document.getElementById("cellPreviewTextarea");try{let t=JSON.parse(e.value);e.value=JSON.stringify(t,null,2),ae()}catch{u("Content is not valid JSON")}}function Vt(){let e=document.getElementById("cellPreviewTextarea");try{let t=JSON.parse(e.value);e.value=JSON.stringify(t),ae()}catch{u("Content is not valid JSON")}}function Wt(){n.cellPreviewWrapEnabled=!n.cellPreviewWrapEnabled;let e=document.getElementById("cellPreviewTextarea"),t=document.getElementById("wrapTextBtn");e.style.whiteSpace=n.cellPreviewWrapEnabled?"pre-wrap":"pre",e.style.overflowX=n.cellPreviewWrapEnabled?"hidden":"auto",t.classList.toggle("active",n.cellPreviewWrapEnabled)}function Ee(e,t,o){let l=document.getElementById(`cell-${e}-${t}`);if(!l)return;l.classList.remove("editing"),o==null?l.classList.add("null-value"):l.classList.remove("null-value");let a=n.tableColumns[t],s=_(o,a?.type,n.dateFormat,a?.name),i=o!=null&&!(o instanceof Uint8Array);l.textContent="";let r=document.createElement("span");if(r.className="cell-text",r.textContent=s,l.appendChild(r),i){let c=document.createElement("span");c.className="expand-icon codicon codicon-link-external",c.title="View full content",l.appendChild(c)}let d=r.scrollWidth>r.clientWidth;l.classList.toggle("has-overflow",d)}function qe(){clearTimeout(n.filterTimer),n.filterTimer=setTimeout(()=>{n.filterQuery=document.getElementById("filterInput").value,n.currentPageIndex=0,v(),$()},300)}function He(){n.rowsPerPage=parseInt(document.getElementById("pageSizeSelect").value,10),n.currentPageIndex=0,v(),$()}function Ge(){let e=document.getElementById("dateFormatSelect");e&&(n.dateFormat=e.value,z(),$())}function Z(e){e>=0&&el.name===t);if(o!==-1){if((e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),n.selectedRowIds.clear(),e.shiftKey&&n.lastSelectedColumnIndex!==null){e.metaKey||e.ctrlKey||(n.selectedCells=[],n.selectedColumns.clear());let l=Math.min(n.lastSelectedColumnIndex,o),a=Math.max(n.lastSelectedColumnIndex,o),s=new Array;if(n.selectedCells.length>0)for(let i of n.selectedCells)i.colIdx>=l&&i.colIdx<=a&&(s[i.rowIdx]||(s[i.rowIdx]=new Set),s[i.rowIdx].add(i.colIdx));for(let i=l;i<=a;i++){let r=n.tableColumns[i].name;n.selectedColumns.add(r);for(let d=0;d0&&a===l)n.selectedCells=n.selectedCells.filter(i=>i.colIdx!==o),n.selectedColumns.delete(t);else{let i=new Set;for(let r of n.selectedCells)r.colIdx===o&&i.add(r.rowIdx);for(let r=0;r0&&a===l&&n.selectedColumns.size===1&&n.selectedColumns.has(t))n.selectedCells=[],n.selectedColumns.clear(),n.lastSelectedColumnIndex=null;else{n.selectedCells=[],n.selectedColumns.clear();for(let i=0;ii.name===n.resizingColumn);if(l===-1)return;let a=document.querySelector(`th[data-column="${n.resizingColumn}"]`);a&&(a.style.width=`${o}px`,a.style.minWidth=`${o}px`,a.style.maxWidth=`${o}px`);let s=document.querySelectorAll(`.data-row td:nth-child(${l+2})`);for(let i of s)i.style.width=`${o}px`,i.style.minWidth=`${o}px`,i.style.maxWidth=`${o}px`;n.pinnedColumns.has(n.resizingColumn)}function nt(){if(!n.resizingColumn)return;let e=document.querySelector(".resize-handle.resizing");e&&e.classList.remove("resizing"),n.resizingColumn=null,document.removeEventListener("mousemove",tt),document.removeEventListener("mouseup",nt),document.body.style.userSelect="",document.body.style.cursor="",z()}function ot(e,t,o){if(e.stopPropagation(),(e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),e.shiftKey&&n.lastSelectedRowIndex!==null){e.metaKey||e.ctrlKey||n.selectedRowIds.clear();let l=Math.min(n.lastSelectedRowIndex,o),a=Math.max(n.lastSelectedRowIndex,o);for(let s=l;s<=a;s++){let i=T(n.gridData[s],s);n.selectedRowIds.add(i)}}else e.ctrlKey||e.metaKey?(n.selectedRowIds.has(t)?n.selectedRowIds.delete(t):n.selectedRowIds.add(t),n.lastSelectedRowIndex=o):n.selectedRowIds.has(t)&&n.selectedRowIds.size===1?(n.selectedRowIds.delete(t),n.lastSelectedRowIndex=null):(n.selectedRowIds.clear(),n.selectedRowIds.add(t),n.lastSelectedRowIndex=o);M(),R(),O()}function ie(e){if(e.stopPropagation(),n.gridData.length===0)return;n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear();let t=!0;for(let o=0;o=s&&m.rowIdx<=i&&m.colIdx>=r&&m.colIdx<=d&&(c[m.rowIdx]||(c[m.rowIdx]=new Set),c[m.rowIdx].add(m.colIdx));for(let m=s;m<=i;m++){let g=c[m];for(let f=r;f<=d;f++)if(!g||!g.has(f)){let p=T(n.gridData[m],m),h=P(n.gridData[m],f);n.selectedCells.push({rowIdx:m,colIdx:f,rowId:p,value:h})}}}else if(e.metaKey||e.ctrlKey){e.preventDefault(),n.selectedRowIds.clear();let s=n.selectedCells.findIndex(i=>i.rowIdx===t&&i.colIdx===o);s>=0?n.selectedCells.splice(s,1):(n.selectedCells.push({rowIdx:t,colIdx:o,rowId:l,value:a}),n.lastSelectedCell={rowIdx:t,colIdx:o})}else if(e.shiftKey&&n.lastSelectedCell){e.preventDefault(),n.selectedRowIds.clear(),n.selectedCells=[];let s=Math.min(n.lastSelectedCell.rowIdx,t),i=Math.max(n.lastSelectedCell.rowIdx,t),r=Math.min(n.lastSelectedCell.colIdx,o),d=Math.max(n.lastSelectedCell.colIdx,o);for(let c=s;c<=i;c++)for(let m=r;m<=d;m++){let g=T(n.gridData[c],c),f=P(n.gridData[c],m);n.selectedCells.push({rowIdx:c,colIdx:m,rowId:g,value:f})}}else n.selectedRowIds.clear(),n.selectedCells=[{rowIdx:t,colIdx:o,rowId:l,value:a}],n.lastSelectedCell={rowIdx:t,colIdx:o},n.selectedColumns.clear();M(),R(),O()}function at(e,t,o,l){if(n.cellEditBehavior==="vscode"){let a=n.tableColumns[o];if(!a)return;let s=n.gridData[t];if(!s)return;let i=P(s,o);n.cellPreviewInfo={rowIdx:t,colIdx:o,rowId:l,columnName:a.name,originalValue:i},be()}else n.cellEditBehavior==="modal"?q(t,o,l):ze(t,o,l)}function st(){document.getElementById("filterInput")?.addEventListener("keyup",qe),document.getElementById("pageSizeSelect")?.addEventListener("change",He),document.getElementById("dateFormatSelect")?.addEventListener("change",Ge),document.getElementById("btnFirst")?.addEventListener("click",()=>Z(0)),document.getElementById("btnPrev")?.addEventListener("click",()=>Z(n.currentPageIndex-1)),document.getElementById("btnNext")?.addEventListener("click",()=>Z(n.currentPageIndex+1)),document.getElementById("btnLast")?.addEventListener("click",()=>Z(n.totalPageCount-1))}function it(){let e=document.getElementById("gridContainer");e&&(e.addEventListener("mousedown",_t),e.addEventListener("keydown",Kt),e.addEventListener("click",qt),e.addEventListener("dblclick",Jt),e.addEventListener("mouseover",Xt),e.addEventListener("scroll",Yt,{passive:!0}))}function _t(e){if(e.target.classList.contains("resize-handle")){e.stopPropagation();let t=e.target.closest(".header-cell");t&&t.dataset.column&&et(e,t.dataset.column)}}function Kt(e){if(e.target.classList.contains("column-filter")){let t=e.target.dataset.column;t&&Xe(e,t)}}function qt(e){let t=e.target;if(t.closest(".grid-header")){Ht(e,t);return}Gt(e,t)}function Ht(e,t){if(t.closest(".filter-apply-btn")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Ie(l.dataset.column);return}if(t.closest(".header-bottom")||t.closest(".column-filter")){e.stopPropagation();return}if(t.closest(".select-column-icon")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Ye(e,l.dataset.column);return}if(t.closest(".pin-icon")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Ze(e,l.dataset.column);return}if(t.closest(".row-number-header")){ie(e);return}let o=t.closest(".header-top");if(o){let l=o.closest(".header-cell");l&&l.dataset.column&&Je(l.dataset.column);return}}function Gt(e,t){if(t.closest(".pin-icon")){let l=t.closest(".data-row");if(l){let a=l.dataset.rowid,s=Q(a);Qe(e,s)}return}if(t.closest(".expand-icon")){let l=t.closest(".data-cell");if(l){let a=parseInt(l.dataset.rowidx,10),s=parseInt(l.dataset.colidx,10),i=Q(l.closest(".data-row").dataset.rowid);q(a,s,i)}return}if(t.closest(".row-number")){let l=t.closest(".data-row");if(l){let a=Q(l.dataset.rowid),s=parseInt(l.dataset.rowidx,10);ot(e,a,s)}return}let o=t.closest(".data-cell");if(o){let l=parseInt(o.dataset.rowidx,10),a=parseInt(o.dataset.colidx,10),s=o.closest(".data-row"),i=Q(s.dataset.rowid);lt(e,l,a,i);return}}function Jt(e){let t=e.target.closest(".data-cell");if(t&&!t.classList.contains("row-number")){let o=parseInt(t.dataset.rowidx,10),l=parseInt(t.dataset.colidx,10),a=t.closest(".data-row"),s=Q(a.dataset.rowid);at(e,o,l,s)}}function Xt(e){let t=e.target.closest(".data-cell");if(t&&!t.classList.contains("checked-overflow")){let o=t.querySelector(".cell-text");if(o){let l=o.scrollWidth>o.clientWidth;t.classList.toggle("has-overflow",l),t.classList.add("checked-overflow")}}}function Yt(e){let t=e.currentTarget;n.scrollPosition.left=t.scrollLeft,n.scrollPosition.top=t.scrollTop,$()}function Q(e){if(e==null)return e;let t=Number(e);return!isNaN(t)&&e.trim()!==""?t:e}function rt(){document.addEventListener("click",e=>{let t=e.target,o=t.closest(".modal-close, .modal-cancel");if(o){let l=o.dataset.modal;l&&U(l)}t.classList.contains("modal-overlay")&&t.classList.add("hidden")}),document.addEventListener("keydown",e=>{if(e.key==="Escape"){let t=document.querySelector(".modal-overlay:not(.hidden)");t&&(t.classList.add("hidden"),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation())}})}function j(e){let t=document.getElementById(e);if(t){t.classList.remove("hidden");let o=t.querySelector("input, select, textarea, button");o&&o.focus()}}function U(e){let t=document.getElementById(e);t&&t.classList.add("hidden")}function ct(){document.getElementById("btnAddRow")?.addEventListener("click",Zt),document.getElementById("btnDeleteRows")?.addEventListener("click",en),document.getElementById("btnAddColumn")?.addEventListener("click",an),document.getElementById("btnSubmitAddRow")?.addEventListener("click",Qt),document.getElementById("btnSubmitDelete")?.addEventListener("click",re),document.getElementById("btnSubmitCreateTable")?.addEventListener("click",ln),document.getElementById("btnAddColumnDef")?.addEventListener("click",()=>mt()),document.getElementById("columnDefinitions")?.addEventListener("click",e=>{let t=e.target.closest(".btn-remove-col");if(t){let o=t.dataset.colid;on(o)}}),document.getElementById("btnSubmitAddColumn")?.addEventListener("click",sn)}function Zt(){if(!n.selectedTable||n.selectedTableType!=="table")return;let e=document.getElementById("addRowForm");e.replaceChildren(),n.tableColumns.forEach(t=>{let o=t.notnull===1&&!t.isPrimaryKey,l=document.createElement("div");l.className="form-field";let a=document.createElement("label");if(a.textContent=t.name,o){let r=document.createElement("span");r.style.color="var(--error-color)",r.textContent="*",a.appendChild(document.createTextNode(" ")),a.appendChild(r)}let s=document.createElement("span");s.style.opacity="0.5",s.textContent=` (${t.type})`,a.appendChild(document.createTextNode(" ")),a.appendChild(s);let i=document.createElement("input");i.type="text",i.dataset.column=t.name,i.dataset.required=o.toString(),t.isPrimaryKey?(i.placeholder="Auto (Primary Key)",i.disabled=!0):o?i.placeholder="Required":i.placeholder="NULL",l.appendChild(a),l.appendChild(i),e.appendChild(l)}),j("addRowModal")}async function Qt(){let e=document.querySelectorAll("#addRowForm input[data-column]:not([disabled])"),t=[];for(let l of e){let a=l.dataset.column,s=l.value.trim();l.dataset.required==="true"&&(s===""||s.toLowerCase()==="null")?(t.push(a),l.style.borderColor="var(--error-color)"):l.style.borderColor=""}if(t.length>0){u(`Required fields missing: ${t.join(", ")}`);return}let o={};for(let l of e){let a=l.dataset.column,s=l.value.trim();s!==""&&(s.toLowerCase()==="null"?o[a]=null:!isNaN(Number(s))&&s!==""?o[a]=Number(s):o[a]=s)}try{u("Inserting row..."),await y.insertRow(n.selectedTable,o),U("addRowModal"),await v(),u("Row inserted - Ctrl+S to save")}catch(l){console.error("Insert failed:",l),u(`Error: ${l.message}`)}}function en(){if(n.selectedColumns.size>0){let e=Array.from(n.selectedColumns);document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${e.length} column${e.length>1?"s":""} (${e.join(", ")})? This will permanently remove the column${e.length>1?"s":""} and all their data.`}else if(n.selectedRowIds.size>0)document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${n.selectedRowIds.size} row${n.selectedRowIds.size>1?"s":""}?`;else return;j("deleteModal")}async function re(){n.selectedColumns.size>0?await nn():n.selectedRowIds.size>0&&await tn()}async function tn(){if(n.selectedRowIds.size===0)return;let e=Array.from(n.selectedRowIds);try{u("Deleting rows..."),await y.deleteRows(n.selectedTable,e),U("deleteModal"),n.selectedRowIds.clear(),await v(),R(),u(`Deleted ${e.length} row${e.length>1?"s":""} - Ctrl+S to save`)}catch(t){console.error("Delete rows failed:",t),u(`Error: ${t.message}`)}}async function nn(){if(n.selectedColumns.size===0)return;let e=Array.from(n.selectedColumns);try{u("Deleting columns...");let t=await y.deleteColumns(n.selectedTable,e);if(t&&t.cancelled){u("Delete cancelled"),U("deleteModal");return}U("deleteModal"),n.selectedColumns.clear(),n.selectedCells=[],n.lastSelectedCell=null,await V(),await K(),await v(),R(),u(`Deleted ${e.length} column${e.length>1?"s":""} - Ctrl+S to save`)}catch(t){console.error("Delete columns failed:",t),u(`Error: ${t.message}`)}}var dt=0;function ut(){document.getElementById("newTableName").value="",document.getElementById("columnDefinitions").replaceChildren(),dt=0,mt(!0),j("createTableModal")}function mt(e=!1){let t=document.getElementById("columnDefinitions"),o=++dt,l=document.createElement("div");l.className="column-def-row",l.id=`colDef_${o}`,Object.assign(l.style,{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center"});let a=document.createElement("input");a.type="text",a.placeholder="Column name",a.className="col-name",a.style.flex="2",e&&(a.value="id"),l.appendChild(a);let s=document.createElement("select");s.className="col-type",s.style.flex="1",["INTEGER","TEXT","REAL","BLOB","NUMERIC"].forEach(f=>{let p=document.createElement("option");p.value=f,p.textContent=f,e&&f==="INTEGER"&&(p.selected=!0),!e&&f==="TEXT"&&(p.selected=!0),s.appendChild(p)}),l.appendChild(s);let i=document.createElement("label");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let r=document.createElement("input");r.type="checkbox",r.className="col-pk",r.style.margin="0",e&&(r.checked=!0),i.appendChild(r),i.appendChild(document.createTextNode(" PK")),l.appendChild(i);let d=document.createElement("label");Object.assign(d.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let c=document.createElement("input");c.type="checkbox",c.className="col-nn",c.style.margin="0",d.appendChild(c),d.appendChild(document.createTextNode(" NN")),l.appendChild(d);let m=document.createElement("button");m.className="icon-button btn-remove-col",m.dataset.colid=o.toString(),m.title="Remove",e&&(m.disabled=!0);let g=document.createElement("span");g.className="codicon codicon-close",m.appendChild(g),l.appendChild(m),t.appendChild(l)}function on(e){let t=document.getElementById(`colDef_${e}`);t&&t.remove()}async function ln(){let e=document.getElementById("newTableName").value.trim();if(!e){u("Error: Table name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid table name");return}let t=[],o=document.querySelectorAll(".column-def-row");for(let l of o){let a=l.querySelector(".col-name").value.trim(),s=l.querySelector(".col-type").value,i=l.querySelector(".col-pk").checked,r=l.querySelector(".col-nn").checked;a&&t.push({name:a,type:s,primaryKey:i,notNull:r})}if(t.length===0){u("Error: At least one column is required");return}try{u("Creating table..."),await y.createTable(e,t),U("createTableModal"),await V(),u(`Table "${e}" created - Ctrl+S to save`)}catch(l){console.error("Create table failed:",l),u(`Error: ${l.message}`)}}function an(){!n.selectedTable||n.selectedTableType!=="table"||(document.getElementById("newColumnName").value="",document.getElementById("newColumnType").value="TEXT",document.getElementById("newColumnDefault").value="",j("addColumnModal"))}async function sn(){let e=document.getElementById("newColumnName").value.trim(),t=document.getElementById("newColumnType").value,o=document.getElementById("newColumnDefault").value.trim();if(!e){u("Error: Column name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid column name");return}try{u("Adding column..."),await y.addColumn(n.selectedTable,e,t,o),U("addColumnModal"),await K(),await v(),u(`Column "${e}" added - Ctrl+S to save`)}catch(l){console.error("Add column failed:",l),u(`Error: ${l.message}`)}}function pt(){let e=document.getElementById("pragmaSettingsContainer");e&&e.addEventListener("change",t=>{let o=t.target;if(o.matches(".setting-extension")){let l=o.dataset.key,a=o.type==="checkbox"?o.checked:o.value;cn(l,a)}else if(o.matches(".setting-pragma")){let l=o.dataset.name,a=o.dataset.type,s=o.value;a==="number"?s=Number(s):a==="bool"&&(s=s==="true"?1:0),dn(l,s)}})}async function ft(){let e=document.getElementById("settingsModal");e&&(e.classList.remove("hidden"),await ve())}async function ve(){let e=document.getElementById("pragmaSettingsContainer");e.textContent="Loading settings...";try{let[t,o]=await Promise.all([y.getPragmas(),y.getExtensionSettings()]);rn(t,o)}catch(t){console.error("Failed to load settings:",t),e.textContent=`Error loading settings: ${t.message}`,e.style.color="var(--error-color)"}}function rn(e,t){let o=document.getElementById("pragmaSettingsContainer");if(!o)return;let l=(x,C)=>x.map(k=>{let L=String(k),D=String(C).toUpperCase()===L.toUpperCase(),N=document.createElement("option");return N.value=L,N.selected=D,N.textContent=L,N});o.replaceChildren();let a=x=>{let C=document.createElement("div");C.className="setting-section-title",Object.assign(C.style,{fontWeight:"600",marginBottom:"8px",paddingBottom:"4px",borderBottom:"1px solid var(--border-color)"}),C.textContent=x,o.appendChild(C)},s=(x,C,k)=>{let L=document.createElement("div");L.className="form-field";let w=document.createElement("label");if(C.type==="checkbox"?(Object.assign(w.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"}),C.style.margin="0",w.appendChild(C),w.appendChild(document.createTextNode(x)),L.appendChild(w)):(w.textContent=x,L.appendChild(w),L.appendChild(C)),k){let D=document.createElement("div");D.className="setting-desc",D.textContent=k,L.appendChild(D)}o.appendChild(L)};if(o.children.length>0){let x=document.createElement("div");x.style.height="16px",o.appendChild(x)}a("Extension Settings");let i=document.createElement("input");i.type="checkbox",i.className="setting-extension",i.dataset.key="autoCommit",i.checked=!!t.autoCommit,s("Auto-Commit Changes",i,"Automatically save changes to disk immediately. If disabled, you must save manually (Ctrl+S).");let r=document.createElement("select");r.className="setting-extension",r.dataset.key="doubleClickBehavior",l(["inline","modal","vscode"],t.cellEditBehavior).forEach(x=>r.appendChild(x)),s("Double Click Behavior",r,"Action when double-clicking a cell");let d=document.createElement("div");d.style.height="16px",o.appendChild(d),a("SQLite Settings (Pragmas)");let c=document.createElement("select");c.className="setting-pragma",c.dataset.name="journal_mode",l(["DELETE","TRUNCATE","PERSIST","MEMORY","WAL","OFF"],e.journal_mode).forEach(x=>c.appendChild(x)),s("Journal Mode",c,"Database journaling mode (WAL is recommended for concurrency)");let m=document.createElement("select");m.className="setting-pragma",m.dataset.name="foreign_keys",m.dataset.type="bool";let g=document.createElement("option");g.value="true",g.textContent="ON";let f=document.createElement("option");f.value="false",f.textContent="OFF",Number(e.foreign_keys)===1?g.selected=!0:f.selected=!0,m.appendChild(g),m.appendChild(f),s("Foreign Keys",m,"Enforce foreign key constraints");let p=document.createElement("select");p.className="setting-pragma",p.dataset.name="synchronous",p.dataset.type="number",[{v:0,t:"OFF (0)"},{v:1,t:"NORMAL (1)"},{v:2,t:"FULL (2)"},{v:3,t:"EXTRA (3)"}].forEach(x=>{let C=document.createElement("option");C.value=x.v,C.textContent=x.t,Number(e.synchronous)===x.v&&(C.selected=!0),p.appendChild(C)}),s("Synchronous",p,"Disk synchronization safety level");let h=document.createElement("select");h.className="setting-pragma",h.dataset.name="locking_mode",l(["NORMAL","EXCLUSIVE"],e.locking_mode).forEach(x=>h.appendChild(x)),s("Locking Mode",h,"");let b=document.createElement("select");b.className="setting-pragma",b.dataset.name="auto_vacuum",b.dataset.type="number",[{v:0,t:"NONE (0)"},{v:1,t:"FULL (1)"},{v:2,t:"INCREMENTAL (2)"}].forEach(x=>{let C=document.createElement("option");C.value=x.v,C.textContent=x.t,Number(e.auto_vacuum)===x.v&&(C.selected=!0),b.appendChild(C)}),s("Auto Vacuum",b,"");let I=document.createElement("input");I.type="number",I.className="setting-pragma",I.dataset.name="cache_size",I.dataset.type="number",I.value=e.cache_size,s("Cache Size",I,"Number of pages (positive) or kilobytes (negative)")}async function cn(e,t){try{await y.updateExtensionSetting(e,t),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await ve()}}async function dn(e,t){try{u(`Updating ${e}...`),await y.setPragma(e,t),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await ve()}}function ht(e,t){let o=new Map;for(let l of e){let a=t&&t[l.colIdx];a&&(o.has(l.colIdx)||o.set(l.colIdx,{name:a.name,type:a.type,values:new Set}),o.get(l.colIdx).values.add(l.value))}return o}function gt(e){let t=Array.from(e||[]);if(t.length===0)return"";if(t.length>1)return"(mixed values)";let o=t[0];return o===null?"NULL":o instanceof Uint8Array?"[BLOB]":String(o)}function yt(e,t,o){let l=[];for(let a of e){let s=t.get(a.colIdx);if(!s)continue;let i=s.dataset||{},r=i.isnull==="true",d=i.ispatch==="true",c=s.value;if(c===""&&!r)continue;let m=o&&o[a.colIdx];if(!m)continue;let g=c,f="set";r?g=null:d?f="json_patch":(m.type==="INTEGER"||m.type==="REAL"||m.type==="NUMERIC")&&!isNaN(Number(c))&&c.trim()!==""&&(g=Number(c)),l.push({rowId:a.rowId,column:m.name,value:g,originalValue:a.value,operation:f,rowIdx:a.rowIdx,colIdx:a.colIdx})}return l}function xt(){let e=document.getElementById("sidebarPanel");if(!e)return;let t=document.getElementById("sidebarFilterInput");t&&t.addEventListener("input",()=>{n.sidebarFilter=t.value,Be()}),e.addEventListener("click",o=>{let l=o.target;if(l.closest("#btnOpenSettings")){ft();return}if(l.closest("#btnOpenCreateTable")){o.stopPropagation(),ut();return}if(l.closest("#btnReload")){yn();return}if(l.closest("#btnApplyBatchUpdate")){mn();return}let a=l.closest(".list-item");if(a){let d=a.dataset.name,c=a.dataset.type;if(d&&c){gn(d,c);return}}let s=l.closest(".section-title");if(s){if(l.closest(".icon-button")||s.id==="btnOpenSettings")return;let d=s.dataset.section;d&&hn(d)}let i=l.closest(".btn-batch-null");if(i){let d=i.closest(".batch-field");if(d){let c=parseInt(d.dataset.colidx,10);pn(c)}return}let r=l.closest(".btn-batch-patch");if(r){let d=r.closest(".batch-field");if(d){let c=parseInt(d.dataset.colidx,10);fn(c,r)}return}})}async function V(){if(n.isDbConnected)try{let e=await y.fetchSchema();n.schemaCache.tables=(e.tables||[]).map(t=>({name:t.identifier})),n.schemaCache.views=(e.views||[]).map(t=>({name:t.identifier})),n.schemaCache.indexes=(e.indexes||[]).map(t=>({name:t.identifier,table:t.parentTable})),Be()}catch(e){console.error("Error loading schema:",e),u("Error loading schema")}}function Se(e,t){return t?e.filter(o=>o.name.toLowerCase().includes(t)):e}function Te(e,t,o,l){let a=document.getElementById(e);a&&(a.textContent=l?`${t}/${o}`:o)}function Ct(e,t,o,l,a){let s=document.getElementById(e);if(!s)return;if(s.replaceChildren(),t.length===0){let r=document.createElement("li");r.className="list-item",r.style.opacity="0.5",r.textContent=a,s.appendChild(r);return}let i=document.createDocumentFragment();t.forEach(r=>{let d=document.createElement("li");d.className="list-item",n.selectedTable===r.name&&n.selectedTableType===o&&d.classList.add("selected"),d.dataset.name=r.name,o&&(d.dataset.type=o),d.title=r.name;let c=document.createElement("span");c.className=`item-icon codicon ${l}`,d.appendChild(c);let m=document.createElement("span");m.className="item-name",m.textContent=r.name,d.appendChild(m),i.appendChild(d)}),s.appendChild(i)}function un(e,t,o){let l=document.getElementById(e);if(!l)return;if(l.replaceChildren(),t.length===0){let s=document.createElement("li");s.className="list-item",s.style.opacity="0.5",s.textContent=o,l.appendChild(s);return}let a=document.createDocumentFragment();t.forEach(s=>{let i=document.createElement("li");i.className="list-item",i.title=`${s.name} on ${s.table}`;let r=document.createElement("span");r.className="item-icon codicon codicon-list-selection",i.appendChild(r);let d=document.createElement("div");d.className="item-content";let c=document.createElement("span");c.className="item-name",c.textContent=s.name,d.appendChild(c);let m=document.createElement("span");m.className="item-detail",m.textContent=s.table,d.appendChild(m),i.appendChild(d),a.appendChild(i)}),l.appendChild(a)}function Be(){let e=n.sidebarFilter.toLowerCase(),t=e.length>0,o=Se(n.schemaCache.tables,e),l=Se(n.schemaCache.views,e),a=Se(n.schemaCache.indexes,e);Te("tablesBadge",o.length,n.schemaCache.tables.length,t),Te("viewsBadge",l.length,n.schemaCache.views.length,t),Te("indexesBadge",a.length,n.schemaCache.indexes.length,t),Ct("tablesList",o,"table","codicon-table",e?"No matching tables":"No tables"),Ct("viewsList",l,"view","codicon-eye",e?"No matching views":"No views"),un("indexesList",a,e?"No matching indexes":"No indexes")}function O(){let e=document.getElementById("batchUpdateSectionTitle"),t=document.getElementById("batchUpdateList"),o=document.getElementById("batchUpdateCount"),l=document.getElementById("batchUpdateFields");if(!e||!t||!o||!l)return;let a=n.selectedCells.length;if(a===0){e.classList.add("hidden"),t.classList.add("hidden");return}e.classList.remove("hidden"),t.classList.remove("hidden"),e.classList.remove("collapsed"),o.textContent=a;let s=ht(n.selectedCells,n.tableColumns);l.replaceChildren();for(let[i,r]of s){let d=gt(r.values),c=document.createElement("div");c.className="form-field batch-field",c.dataset.colidx=i,c.style.marginBottom="8px";let m=document.createElement("label");m.style.fontSize="11px",m.style.color="var(--text-secondary)";let g=document.createTextNode(r.name+" ");m.appendChild(g);let f=document.createElement("span");f.style.opacity="0.7",f.textContent=r.type||"",m.appendChild(f),c.appendChild(m);let p=document.createElement("div");p.style.display="flex",p.style.gap="4px";let h=document.createElement("input");h.type="text",h.className="batch-input",h.placeholder=d,h.dataset.colidx=i,h.style.flex="1",h.style.minWidth="0",p.appendChild(h);let b=document.createElement("button");b.className="btn-secondary btn-batch-null",b.style.padding="2px 6px",b.title="Set to NULL",b.textContent="NULL",p.appendChild(b);let I=document.createElement("button");I.className="btn-secondary btn-batch-patch",I.style.padding="2px 6px",I.title="JSON Patch",I.textContent="{}",p.appendChild(I),c.appendChild(p),l.appendChild(c)}}async function mn(){if(n.selectedCells.length===0)return;let e=document.querySelectorAll(".batch-input"),t=new Map;for(let l of e){let a=parseInt(l.dataset.colidx,10);if(t.set(a,l),l.dataset.ispatch==="true")try{JSON.parse(l.value)}catch{let i=n.tableColumns[a];u(`Invalid JSON for patch in ${i.name}`);return}}let o=yt(n.selectedCells,t,n.tableColumns);if(o.length===0){u("No values entered for batch update");return}try{u(`Updating ${o.length} cells...`);let l=`Batch update ${o.length} cells`,a=o.map(r=>({rowId:r.rowId,column:r.column,value:r.value,originalValue:r.originalValue,operation:r.operation}));if(await y.updateCellBatch(n.selectedTable,a,l),!o.some(r=>r.operation==="json_patch"))for(let r of o)n.gridData[r.rowIdx][r.colIdx+B()]=r.value;await v(!1);let i=[];for(let r of n.selectedCells){let d=n.gridData[r.rowIdx][r.colIdx+B()];i.push({...r,value:d})}n.selectedCells=i,O(),u("Batch update completed")}catch(l){console.error("Batch update failed:",l),u(`Batch update failed: ${l.message}`)}}function pn(e){let t=document.querySelector(`.batch-input[data-colidx="${e}"]`),o=document.querySelector(`.batch-field[data-colidx="${e}"] .btn-batch-patch`);t&&(t.value="",t.placeholder="SET TO NULL",t.dataset.isnull="true",t.dataset.ispatch="false",t.style.fontStyle="italic",o&&(o.style.background="",o.style.color=""))}function fn(e,t){let o=document.querySelector(`.batch-input[data-colidx="${e}"]`);o&&(o.dataset.ispatch==="true"?(o.dataset.ispatch="false",o.placeholder="(mixed values)",t.style.background="",t.style.color=""):(o.dataset.ispatch="true",o.dataset.isnull="false",o.placeholder='JSON Patch (e.g. {"a": 1})',o.style.fontStyle="normal",t.style.background="var(--accent-color)",t.style.color="white"))}function hn(e){let t=document.getElementById(`${e}List`),o=document.querySelector(`.section-title[data-section="${e}"]`);t&&o&&(t.classList.toggle("hidden"),o.classList.toggle("collapsed"))}async function gn(e,t){n.selectedTable=e,n.selectedTableType=t,n.currentPageIndex=0,n.sortedColumn=null,n.sortAscending=!0,n.filterQuery="",n.columnFilters={},n.selectedRowIds.clear(),n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),n.pinnedColumns.clear(),n.pinnedRowIds.clear(),n.columnWidths={},n.scrollPosition={top:0,left:0},Be();let o=document.getElementById("tableNameLabel");o&&(o.textContent=e);let l=document.getElementById("filterInput");l&&(l.value=""),await K(),await v(!0,!1),$()}async function yn(){if(n.isDbConnected)try{u("Reloading..."),await y.refreshFile(),await V(),n.selectedTable&&(await K(),await v()),u("Reloaded")}catch(e){console.error("Reload failed:",e),u(`Reload failed: ${e.message}`)}}function wt(){document.getElementById("btnExport")?.addEventListener("click",Cn),document.getElementById("btnSubmitExport")?.addEventListener("click",xn),document.getElementById("exportFormat")?.addEventListener("change",bt)}function Cn(){if(!n.selectedTable)return;let e=document.getElementById("exportFormat");e&&(e.value="csv");let t=document.getElementById("exportColumns");t&&(t.replaceChildren(),n.tableColumns.forEach(o=>{let l=document.createElement("div"),a=document.createElement("label");Object.assign(a.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let s=document.createElement("input");s.type="checkbox",s.className="export-col-check",s.value=o.name,s.checked=!0,s.style.margin="0",a.appendChild(s),a.appendChild(document.createTextNode(o.name)),t.appendChild(a)})),bt(),j("exportModal")}function bt(){let e=document.getElementById("exportFormat").value,t=document.getElementById("exportOptions");if(t.replaceChildren(),e==="csv"||e==="excel"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportHeader",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Headers")),t.appendChild(o)}else if(e==="sql"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportTableName",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Table Name")),t.appendChild(o)}}async function xn(){let e=document.getElementById("exportFormat").value,t=document.querySelectorAll(".export-col-check:checked"),o=Array.from(t).map(a=>a.value);if(o.length===0){u("Error: Select at least one column");return}let l={};if(e==="csv"||e==="excel"?l.header=document.getElementById("exportHeader")?.checked??!0:e==="sql"&&(l.includeTableName=document.getElementById("exportTableName")?.checked??!0),n.selectedTableType==="table"){let a=Array.from(n.selectedRowIds);a.length>0&&(l.rowIds=a)}try{u("Exporting..."),U("exportModal"),await y.exportTable({table:n.selectedTable},o,null,null,{format:e,...l}),u("Export initiated")}catch(a){console.error("Export failed:",a),u(`Export failed: ${a.message}`)}}async function Et(){if(n.selectedCells.length!==0)try{let e;if(n.selectedCells.length===1){let t=n.selectedCells[0].value;t==null?e="":t instanceof Uint8Array?e="[BLOB]":e=String(t)}else{let t=[...new Set(n.selectedCells.map(s=>s.rowIdx))].sort((s,i)=>s-i),o=[...new Set(n.selectedCells.map(s=>s.colIdx))].sort((s,i)=>s-i),l=new Map;for(let s of n.selectedCells)l.set(`${s.rowIdx},${s.colIdx}`,s.value);let a=[];for(let s of t){let i=[];for(let r of o){let d=`${s},${r}`,c=l.has(d)?l.get(d):"";c==null?c="":c instanceof Uint8Array?c="[BLOB]":(c=String(c),c=c.replace(/\t/g," ").replace(/\n/g," ")),i.push(c)}a.push(i.join(" "))}e=a.join(` +`)}await navigator.clipboard.writeText(e),u(`Copied ${n.selectedCells.length} cell${n.selectedCells.length>1?"s":""}`)}catch(e){console.error("Copy failed:",e),u("Copy failed: "+e.message)}}async function It(){if(n.selectedRowIds.size!==0)try{let e=[];for(let l=0;ld==null?"":d instanceof Uint8Array?"[BLOB]":String(d));e.push(r.join(" "))}}let o=[n.tableColumns.map(l=>l.name).join(" "),...e].join(` +`);await navigator.clipboard.writeText(o),u(`Copied ${e.length} row${e.length>1?"s":""} to clipboard`)}catch(e){console.error("Copy failed:",e),u("Copy failed: "+e.message)}}async function vt(){if(n.selectedCells.length!==0){if(n.selectedTableType!=="table"){u("Views are read-only");return}try{u("Clearing cells...");let e=[];for(let o of n.selectedCells){let l=n.tableColumns[o.colIdx];if(!l)continue;let s=l.notnull===1?"":null;e.push({rowId:o.rowId,column:l.name,value:s,originalValue:o.value,rowIdx:o.rowIdx,colIdx:o.colIdx})}let t=`Clear ${e.length} cell${e.length>1?"s":""}`;await y.updateCellBatch(n.selectedTable,e,t);for(let o of e)n.gridData[o.rowIdx][o.colIdx+B()]=o.value;n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),await v(),R(),u(`${t} - Ctrl+S to save`)}catch(e){console.error("Clear cells failed:",e),u(`Clear failed: ${e.message}`)}}}var ce=50*1024*1024,Le=!1;function St(){let e=document.getElementById("gridContainer");if(!e){console.error("gridContainer not found");return}document.addEventListener("dragover",t=>t.preventDefault()),document.addEventListener("drop",t=>t.preventDefault()),e.addEventListener("dragover",wn),e.addEventListener("dragleave",bn),e.addEventListener("drop",En)}var F=null;function wn(e){e.preventDefault(),e.dataTransfer.dropEffect="copy";let t=e.target.closest(".data-cell");t&&!t.classList.contains("row-number")?(F&&F!==t&&F.classList.remove("drag-over"),t.classList.add("drag-over"),F=t):F&&(F.classList.remove("drag-over"),F=null)}function bn(e){e.target}async function En(e){e.preventDefault(),F&&(F.classList.remove("drag-over"),F=null);let t=e.target.closest(".data-cell");if(!t||t.classList.contains("row-number"))return;if(e.dataTransfer.files.length>0){let l=e.dataTransfer.files[0];await In(t,l.name,l);return}let o=e.dataTransfer.getData("text/uri-list");if(o){let l=o.split(/\r?\n/);if(l.length>0&&l[0]){let a=l[0],s="unknown_file";try{let i=a.split("/");s=decodeURIComponent(i[i.length-1])}catch(i){console.warn("Failed to parse name from URI",i)}await vn(t,s,a);return}}}async function In(e,t,o){if(o.size>ce){let l=(o.size/1048576).toFixed(1),a=(ce/(1024*1024)).toFixed(0);u(`File too large (${l}MB). Maximum is ${a}MB.`);return}try{u(`Reading ${t}...`);let l=await Sn(o),a=new Uint8Array(l);await Tt(e,t,a)}catch(l){console.error("File read failed:",l),u(`File read failed: ${l.message}`)}}async function vn(e,t,o){try{u(`Fetching ${t}...`);let l=await y.readWorkspaceFileUri(o),a;if(l instanceof Uint8Array)a=l;else if(l&&l.type==="Buffer"&&Array.isArray(l.data))a=new Uint8Array(l.data);else if(l&&typeof l=="object"&&Object.keys(l).some(s=>!isNaN(s)))a=new Uint8Array(Object.values(l));else throw console.error("Unknown data format from backend:",l),new Error("Received invalid data format from backend");await Tt(e,t,a)}catch(l){console.error("URI upload failed:",l),u(`Upload failed: ${l.message}`)}}async function Tt(e,t,o){if(Le){u("Upload already in progress...");return}if(o.byteLength>ce){let d=(o.byteLength/1048576).toFixed(1),c=(ce/(1024*1024)).toFixed(0);u(`File too large (${d}MB). Maximum is ${c}MB.`);return}let l=parseInt(e.dataset.rowidx,10),a=parseInt(e.dataset.colidx,10);if(!n.gridData)return;let s=n.gridData[l];if(!s)return;let i=T(s,l),r=n.tableColumns[a];if(n.selectedTableType!=="table"){u("Cannot upload to a view");return}Le=!0,n.isLoadingData=!0;try{u(`Uploading ${t} (${Tn(o.byteLength)})...`);let d=s[a+B()];await y.updateCell(n.selectedTable,i,r.name,o,d),n.gridData[l][a+B()]=o,Bn(e,o),u(`Uploaded ${t}`)}catch(d){console.error("Upload failed:",d);let c=d.message||String(d);c.includes("timeout")&&(c="Upload timed out. Try a smaller file."),u(`Upload failed: ${c}`)}finally{Le=!1,n.isLoadingData=!1}}function Sn(e){return new Promise((t,o)=>{let l=new FileReader;l.onload=()=>t(l.result),l.onerror=()=>o(l.error),l.readAsArrayBuffer(e)})}function Tn(e){if(e===0)return"0 B";let t=1024,o=["B","KB","MB","GB"],l=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,l)).toFixed(2))+" "+o[l]}function Bn(e,t){let o=_(t);e.textContent="";let l=document.createElement("span");l.className="cell-text",l.textContent=o,e.appendChild(l);let a=document.createElement("span");a.className="expand-icon codicon codicon-link-external",a.title="View full content",e.appendChild(a),e.classList.remove("null-value")}var Bt={async refreshContent(e){return n.isDbConnected&&(await V(),!(n.schemaCache.tables.some(o=>o.name===n.selectedTable)||n.schemaCache.views.some(o=>o.name===n.selectedTable))&&n.selectedTable?(n.selectedTable=null,n.selectedTableType=null,document.getElementById("tableNameLabel").textContent="No table selected",xe()):n.selectedTable&&await v(!1)),{success:!0}},async updateColorScheme(e){return document.documentElement.style.colorScheme=e,{success:!0}},async updateCellEditBehavior(e){return n.cellEditBehavior=e,{success:!0}}};function Ln(){window.addEventListener("message",e=>{let t=e.data;if(t&&t.kind==="invoke"){let{correlationId:l,methodName:a,parameters:s}=t,i=Bt[a];typeof i=="function"?Promise.resolve(i.apply(Bt,s||[])).then(r=>{Ae(l,r)}).catch(r=>{ye(l,r instanceof Error?r.message:String(r))}):ye(l,`Unknown method: ${a}`);return}if(!t||t.channel!=="rpc")return;let o=t.content;o&&o.kind==="response"&&ke(o)})}Ln();async function Rn(){try{xt(),ct(),wt(),rt(),pt(),Oe(),st(),it(),Me(),St();let e=document.getElementById("openInVsCodeBtn");e&&(e.style.display="none"),u("Connecting to database...");let t=await y.initialize();n.isDbConnected=!0,await y.ping(),await V(),u("Ready"),xe(),document.addEventListener("keydown",async o=>{if(o.key==="Escape"&&!n.editingCellInfo&&!document.querySelector(".modal-overlay:not(.hidden)")&&oe(),(o.metaKey||o.ctrlKey)&&o.key==="c"){if(n.editingCellInfo||document.activeElement.tagName==="INPUT")return;n.selectedCells.length>0?(o.preventDefault(),await Et()):n.selectedRowIds.size>0&&(o.preventDefault(),await It())}if((o.metaKey||o.ctrlKey)&&o.key==="a"){if(n.editingCellInfo||document.activeElement.tagName==="INPUT")return;n.selectedTable&&(o.preventDefault(),ie(o))}if((o.metaKey||o.ctrlKey)&&(o.key==="Delete"||o.key==="Backspace")){if(n.editingCellInfo||document.activeElement.tagName==="INPUT"||document.activeElement.tagName==="TEXTAREA")return;n.selectedTable&&n.selectedTableType==="table"&&(o.preventDefault(),n.selectedColumns.size>0?await re():n.selectedRowIds.size>0?await re():n.selectedCells.length>0&&await vt())}})}catch(e){console.error("Init error:",e),ne(e.message)}}Rn();})(); From 9ea707a277d198b4d004abf3ebc2c52da556316d Mon Sep 17 00:00:00 2001 From: zknpr Date: Sat, 30 May 2026 23:00:05 +0200 Subject: [PATCH 3/3] test(ui): address remaining batch-update review nits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - batch-update-logic.js: normalize column type to upper-case before numeric coercion (Gemini — SQLite reports declared types verbatim, e.g. 'integer', so the case-sensitive check could miss lowercase numeric columns) - sidebar.js: guard colDef?.name in the invalid-JSON validation path against a stale/out-of-bounds colIdx (Codex non-blocking caveat) - tests: add NUMERIC + lowercase-type coercion cases (suite: 330 passing) Co-Authored-By: Claude Opus 4.8 (1M context) --- core/ui/modules/batch-update-logic.js | 8 ++++++-- core/ui/modules/sidebar.js | 2 +- core/ui/viewer.html | 2 +- tests/unit/batch-update-logic.test.ts | 11 +++++++++++ website/public/sqlite-viewer/viewer.html | 2 +- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/core/ui/modules/batch-update-logic.js b/core/ui/modules/batch-update-logic.js index 5313855..f030bbe 100644 --- a/core/ui/modules/batch-update-logic.js +++ b/core/ui/modules/batch-update-logic.js @@ -79,9 +79,13 @@ export function prepareBatchUpdates(selectedCells, inputsByCol, tableColumns) { finalValue = null; } else if (isPatch) { operation = 'json_patch'; - } else if (colDef.type === 'INTEGER' || colDef.type === 'REAL' || colDef.type === 'NUMERIC') { + } else { // Coerce numeric column types when the input parses as a number. - if (!isNaN(Number(value)) && value.trim() !== '') { + // Normalize case: SQLite stores the declared type verbatim, so a column + // may report e.g. 'integer' rather than 'INTEGER'. + const colType = (colDef.type || '').toUpperCase(); + if ((colType === 'INTEGER' || colType === 'REAL' || colType === 'NUMERIC') + && !isNaN(Number(value)) && value.trim() !== '') { finalValue = Number(value); } } diff --git a/core/ui/modules/sidebar.js b/core/ui/modules/sidebar.js index 7061237..794e8f7 100644 --- a/core/ui/modules/sidebar.js +++ b/core/ui/modules/sidebar.js @@ -329,7 +329,7 @@ export async function applyBatchUpdate() { JSON.parse(input.value); } catch (e) { const colDef = state.tableColumns[colIdx]; - updateStatus(`Invalid JSON for patch in ${colDef.name}`); + updateStatus(`Invalid JSON for patch in ${colDef?.name ?? `column ${colIdx}`}`); return; } } diff --git a/core/ui/viewer.html b/core/ui/viewer.html index c4e0c63..e632cbb 100644 --- a/core/ui/viewer.html +++ b/core/ui/viewer.html @@ -381,7 +381,7 @@ Error ${X(e)} - `)}function R(){let e=t.selectedTable&&t.selectedTableType==="table",n=t.selectedRowIds.size>0,o=t.selectedColumns.size>0,l=document.getElementById("btnAddRow"),a=document.getElementById("btnAddColumn"),s=document.getElementById("btnDeleteRows"),i=document.getElementById("btnExport");l&&(l.disabled=!e),a&&(a.disabled=!e),s&&(s.disabled=!e||!n&&!o),i&&(i.disabled=!t.selectedTable)}function Me(){let e=document.getElementById("sidebarPanel"),n=document.getElementById("resizeHandle");if(!e||!n)return;let o=!1;n.addEventListener("mousedown",l=>{o=!0,document.body.style.cursor="col-resize",l.preventDefault()}),document.addEventListener("mousemove",l=>{if(!o)return;let a=Math.max(150,Math.min(400,l.clientX));e.style.width=a+"px"}),document.addEventListener("mouseup",()=>{o&&(o=!1,document.body.style.cursor="")})}function B(){return t.selectedTableType==="table"?1:0}function T(e,n){return t.selectedTableType==="table"?e[0]:t.currentPageIndex*t.rowsPerPage+n}function P(e,n){return e[n+B()]}function Ue(){document.addEventListener("click",e=>{let n=e.target,o=n.closest(".modal-close, .modal-cancel");if(o){let l=o.dataset.modal;l&&O(l)}n.classList.contains("modal-overlay")&&n.classList.add("hidden")}),document.addEventListener("keydown",e=>{if(e.key==="Escape"){let n=document.querySelector(".modal-overlay:not(.hidden)");n&&(n.classList.add("hidden"),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation())}})}function W(e){let n=document.getElementById(e);if(n){n.classList.remove("hidden");let o=n.querySelector("input, select, textarea, button");o&&o.focus()}}function O(e){let n=document.getElementById(e);n&&n.classList.add("hidden")}function Oe(){document.getElementById("btnAddRow")?.addEventListener("click",zt),document.getElementById("btnDeleteRows")?.addEventListener("click",jt),document.getElementById("btnAddColumn")?.addEventListener("click",Ht),document.getElementById("btnSubmitAddRow")?.addEventListener("click",Vt),document.getElementById("btnSubmitDelete")?.addEventListener("click",ae),document.getElementById("btnSubmitCreateTable")?.addEventListener("click",Kt),document.getElementById("btnAddColumnDef")?.addEventListener("click",()=>je()),document.getElementById("columnDefinitions")?.addEventListener("click",e=>{let n=e.target.closest(".btn-remove-col");if(n){let o=n.dataset.colid;qt(o)}}),document.getElementById("btnSubmitAddColumn")?.addEventListener("click",Gt)}function zt(){if(!t.selectedTable||t.selectedTableType!=="table")return;let e=document.getElementById("addRowForm");e.replaceChildren(),t.tableColumns.forEach(n=>{let o=n.notnull===1&&!n.isPrimaryKey,l=document.createElement("div");l.className="form-field";let a=document.createElement("label");if(a.textContent=n.name,o){let r=document.createElement("span");r.style.color="var(--error-color)",r.textContent="*",a.appendChild(document.createTextNode(" ")),a.appendChild(r)}let s=document.createElement("span");s.style.opacity="0.5",s.textContent=` (${n.type})`,a.appendChild(document.createTextNode(" ")),a.appendChild(s);let i=document.createElement("input");i.type="text",i.dataset.column=n.name,i.dataset.required=o.toString(),n.isPrimaryKey?(i.placeholder="Auto (Primary Key)",i.disabled=!0):o?i.placeholder="Required":i.placeholder="NULL",l.appendChild(a),l.appendChild(i),e.appendChild(l)}),W("addRowModal")}async function Vt(){let e=document.querySelectorAll("#addRowForm input[data-column]:not([disabled])"),n=[];for(let l of e){let a=l.dataset.column,s=l.value.trim();l.dataset.required==="true"&&(s===""||s.toLowerCase()==="null")?(n.push(a),l.style.borderColor="var(--error-color)"):l.style.borderColor=""}if(n.length>0){u(`Required fields missing: ${n.join(", ")}`);return}let o={};for(let l of e){let a=l.dataset.column,s=l.value.trim();s!==""&&(s.toLowerCase()==="null"?o[a]=null:!isNaN(Number(s))&&s!==""?o[a]=Number(s):o[a]=s)}try{u("Inserting row..."),await y.insertRow(t.selectedTable,o),O("addRowModal"),await I(),u("Row inserted - Ctrl+S to save")}catch(l){console.error("Insert failed:",l),u(`Error: ${l.message}`)}}function jt(){if(t.selectedColumns.size>0){let e=Array.from(t.selectedColumns);document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${e.length} column${e.length>1?"s":""} (${e.join(", ")})? This will permanently remove the column${e.length>1?"s":""} and all their data.`}else if(t.selectedRowIds.size>0)document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${t.selectedRowIds.size} row${t.selectedRowIds.size>1?"s":""}?`;else return;W("deleteModal")}async function ae(){t.selectedColumns.size>0?await _t():t.selectedRowIds.size>0&&await Wt()}async function Wt(){if(t.selectedRowIds.size===0)return;let e=Array.from(t.selectedRowIds);try{u("Deleting rows..."),await y.deleteRows(t.selectedTable,e),O("deleteModal"),t.selectedRowIds.clear(),await I(),R(),u(`Deleted ${e.length} row${e.length>1?"s":""} - Ctrl+S to save`)}catch(n){console.error("Delete rows failed:",n),u(`Error: ${n.message}`)}}async function _t(){if(t.selectedColumns.size===0)return;let e=Array.from(t.selectedColumns);try{u("Deleting columns...");let n=await y.deleteColumns(t.selectedTable,e);if(n&&n.cancelled){u("Delete cancelled"),O("deleteModal");return}O("deleteModal"),t.selectedColumns.clear(),t.selectedCells=[],t.lastSelectedCell=null,await V(),await z(),await I(),R(),u(`Deleted ${e.length} column${e.length>1?"s":""} - Ctrl+S to save`)}catch(n){console.error("Delete columns failed:",n),u(`Error: ${n.message}`)}}var ze=0;function Ve(){document.getElementById("newTableName").value="",document.getElementById("columnDefinitions").replaceChildren(),ze=0,je(!0),W("createTableModal")}function je(e=!1){let n=document.getElementById("columnDefinitions"),o=++ze,l=document.createElement("div");l.className="column-def-row",l.id=`colDef_${o}`,Object.assign(l.style,{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center"});let a=document.createElement("input");a.type="text",a.placeholder="Column name",a.className="col-name",a.style.flex="2",e&&(a.value="id"),l.appendChild(a);let s=document.createElement("select");s.className="col-type",s.style.flex="1",["INTEGER","TEXT","REAL","BLOB","NUMERIC"].forEach(f=>{let p=document.createElement("option");p.value=f,p.textContent=f,e&&f==="INTEGER"&&(p.selected=!0),!e&&f==="TEXT"&&(p.selected=!0),s.appendChild(p)}),l.appendChild(s);let i=document.createElement("label");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let r=document.createElement("input");r.type="checkbox",r.className="col-pk",r.style.margin="0",e&&(r.checked=!0),i.appendChild(r),i.appendChild(document.createTextNode(" PK")),l.appendChild(i);let d=document.createElement("label");Object.assign(d.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let c=document.createElement("input");c.type="checkbox",c.className="col-nn",c.style.margin="0",d.appendChild(c),d.appendChild(document.createTextNode(" NN")),l.appendChild(d);let m=document.createElement("button");m.className="icon-button btn-remove-col",m.dataset.colid=o.toString(),m.title="Remove",e&&(m.disabled=!0);let h=document.createElement("span");h.className="codicon codicon-close",m.appendChild(h),l.appendChild(m),n.appendChild(l)}function qt(e){let n=document.getElementById(`colDef_${e}`);n&&n.remove()}async function Kt(){let e=document.getElementById("newTableName").value.trim();if(!e){u("Error: Table name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid table name");return}let n=[],o=document.querySelectorAll(".column-def-row");for(let l of o){let a=l.querySelector(".col-name").value.trim(),s=l.querySelector(".col-type").value,i=l.querySelector(".col-pk").checked,r=l.querySelector(".col-nn").checked;a&&n.push({name:a,type:s,primaryKey:i,notNull:r})}if(n.length===0){u("Error: At least one column is required");return}try{u("Creating table..."),await y.createTable(e,n),O("createTableModal"),await V(),u(`Table "${e}" created - Ctrl+S to save`)}catch(l){console.error("Create table failed:",l),u(`Error: ${l.message}`)}}function Ht(){!t.selectedTable||t.selectedTableType!=="table"||(document.getElementById("newColumnName").value="",document.getElementById("newColumnType").value="TEXT",document.getElementById("newColumnDefault").value="",W("addColumnModal"))}async function Gt(){let e=document.getElementById("newColumnName").value.trim(),n=document.getElementById("newColumnType").value,o=document.getElementById("newColumnDefault").value.trim();if(!e){u("Error: Column name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid column name");return}try{u("Adding column..."),await y.addColumn(t.selectedTable,e,n,o),O("addColumnModal"),await z(),await I(),u(`Column "${e}" added - Ctrl+S to save`)}catch(l){console.error("Add column failed:",l),u(`Error: ${l.message}`)}}function We(){let e=document.getElementById("pragmaSettingsContainer");e&&e.addEventListener("change",n=>{let o=n.target;if(o.matches(".setting-extension")){let l=o.dataset.key,a=o.type==="checkbox"?o.checked:o.value;Xt(l,a)}else if(o.matches(".setting-pragma")){let l=o.dataset.name,a=o.dataset.type,s=o.value;a==="number"?s=Number(s):a==="bool"&&(s=s==="true"?1:0),Yt(l,s)}})}async function _e(){let e=document.getElementById("settingsModal");e&&(e.classList.remove("hidden"),await xe())}async function xe(){let e=document.getElementById("pragmaSettingsContainer");e.textContent="Loading settings...";try{let[n,o]=await Promise.all([y.getPragmas(),y.getExtensionSettings()]);Jt(n,o)}catch(n){console.error("Failed to load settings:",n),e.textContent=`Error loading settings: ${n.message}`,e.style.color="var(--error-color)"}}function Jt(e,n){let o=document.getElementById("pragmaSettingsContainer");if(!o)return;let l=(x,C)=>x.map(k=>{let L=String(k),N=String(C).toUpperCase()===L.toUpperCase(),D=document.createElement("option");return D.value=L,D.selected=N,D.textContent=L,D});o.replaceChildren();let a=x=>{let C=document.createElement("div");C.className="setting-section-title",Object.assign(C.style,{fontWeight:"600",marginBottom:"8px",paddingBottom:"4px",borderBottom:"1px solid var(--border-color)"}),C.textContent=x,o.appendChild(C)},s=(x,C,k)=>{let L=document.createElement("div");L.className="form-field";let b=document.createElement("label");if(C.type==="checkbox"?(Object.assign(b.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"}),C.style.margin="0",b.appendChild(C),b.appendChild(document.createTextNode(x)),L.appendChild(b)):(b.textContent=x,L.appendChild(b),L.appendChild(C)),k){let N=document.createElement("div");N.className="setting-desc",N.textContent=k,L.appendChild(N)}o.appendChild(L)};if(o.children.length>0){let x=document.createElement("div");x.style.height="16px",o.appendChild(x)}a("Extension Settings");let i=document.createElement("input");i.type="checkbox",i.className="setting-extension",i.dataset.key="autoCommit",i.checked=!!n.autoCommit,s("Auto-Commit Changes",i,"Automatically save changes to disk immediately. If disabled, you must save manually (Ctrl+S).");let r=document.createElement("select");r.className="setting-extension",r.dataset.key="doubleClickBehavior",l(["inline","modal","vscode"],n.cellEditBehavior).forEach(x=>r.appendChild(x)),s("Double Click Behavior",r,"Action when double-clicking a cell");let d=document.createElement("div");d.style.height="16px",o.appendChild(d),a("SQLite Settings (Pragmas)");let c=document.createElement("select");c.className="setting-pragma",c.dataset.name="journal_mode",l(["DELETE","TRUNCATE","PERSIST","MEMORY","WAL","OFF"],e.journal_mode).forEach(x=>c.appendChild(x)),s("Journal Mode",c,"Database journaling mode (WAL is recommended for concurrency)");let m=document.createElement("select");m.className="setting-pragma",m.dataset.name="foreign_keys",m.dataset.type="bool";let h=document.createElement("option");h.value="true",h.textContent="ON";let f=document.createElement("option");f.value="false",f.textContent="OFF",Number(e.foreign_keys)===1?h.selected=!0:f.selected=!0,m.appendChild(h),m.appendChild(f),s("Foreign Keys",m,"Enforce foreign key constraints");let p=document.createElement("select");p.className="setting-pragma",p.dataset.name="synchronous",p.dataset.type="number",[{v:0,t:"OFF (0)"},{v:1,t:"NORMAL (1)"},{v:2,t:"FULL (2)"},{v:3,t:"EXTRA (3)"}].forEach(x=>{let C=document.createElement("option");C.value=x.v,C.textContent=x.t,Number(e.synchronous)===x.v&&(C.selected=!0),p.appendChild(C)}),s("Synchronous",p,"Disk synchronization safety level");let g=document.createElement("select");g.className="setting-pragma",g.dataset.name="locking_mode",l(["NORMAL","EXCLUSIVE"],e.locking_mode).forEach(x=>g.appendChild(x)),s("Locking Mode",g,"");let w=document.createElement("select");w.className="setting-pragma",w.dataset.name="auto_vacuum",w.dataset.type="number",[{v:0,t:"NONE (0)"},{v:1,t:"FULL (1)"},{v:2,t:"INCREMENTAL (2)"}].forEach(x=>{let C=document.createElement("option");C.value=x.v,C.textContent=x.t,Number(e.auto_vacuum)===x.v&&(C.selected=!0),w.appendChild(C)}),s("Auto Vacuum",w,"");let v=document.createElement("input");v.type="number",v.className="setting-pragma",v.dataset.name="cache_size",v.dataset.type="number",v.value=e.cache_size,s("Cache Size",v,"Number of pages (positive) or kilobytes (negative)")}async function Xt(e,n){try{await y.updateExtensionSetting(e,n),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await xe()}}async function Yt(e,n){try{u(`Updating ${e}...`),await y.setPragma(e,n),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await xe()}}function qe(e,n){let o=new Map;for(let l of e){let a=n&&n[l.colIdx];a&&(o.has(l.colIdx)||o.set(l.colIdx,{name:a.name,type:a.type,values:new Set}),o.get(l.colIdx).values.add(l.value))}return o}function Ke(e){let n=Array.from(e||[]);if(n.length===0)return"";if(n.length>1)return"(mixed values)";let o=n[0];return o===null?"NULL":o instanceof Uint8Array?"[BLOB]":String(o)}function He(e,n,o){let l=[];for(let a of e){let s=n.get(a.colIdx);if(!s)continue;let i=s.dataset||{},r=i.isnull==="true",d=i.ispatch==="true",c=s.value;if(c===""&&!r)continue;let m=o&&o[a.colIdx];if(!m)continue;let h=c,f="set";r?h=null:d?f="json_patch":(m.type==="INTEGER"||m.type==="REAL"||m.type==="NUMERIC")&&!isNaN(Number(c))&&c.trim()!==""&&(h=Number(c)),l.push({rowId:a.rowId,column:m.name,value:h,originalValue:a.value,operation:f,rowIdx:a.rowIdx,colIdx:a.colIdx})}return l}function Je(){let e=document.getElementById("sidebarPanel");if(!e)return;let n=document.getElementById("sidebarFilterInput");n&&n.addEventListener("input",()=>{t.sidebarFilter=n.value,Y()}),e.addEventListener("click",o=>{let l=o.target;if(l.closest("#btnOpenSettings")){_e();return}if(l.closest("#btnOpenCreateTable")){o.stopPropagation(),Ve();return}if(l.closest("#btnReload")){ln();return}if(l.closest("#btnApplyBatchUpdate")){Zt();return}let a=l.closest(".list-item");if(a){let d=a.dataset.name,c=a.dataset.type;if(d&&c){on(d,c);return}}let s=l.closest(".section-title");if(s){if(l.closest(".icon-button")||s.id==="btnOpenSettings")return;let d=s.dataset.section;d&&nn(d)}let i=l.closest(".btn-batch-null");if(i){let d=i.closest(".batch-field");if(d){let c=parseInt(d.dataset.colidx,10);en(c)}return}let r=l.closest(".btn-batch-patch");if(r){let d=r.closest(".batch-field");if(d){let c=parseInt(d.dataset.colidx,10);tn(c,r)}return}})}async function V(){if(t.isDbConnected)try{let e=await y.fetchSchema();t.schemaCache.tables=(e.tables||[]).map(n=>({name:n.identifier})),t.schemaCache.views=(e.views||[]).map(n=>({name:n.identifier})),t.schemaCache.indexes=(e.indexes||[]).map(n=>({name:n.identifier,table:n.parentTable})),Y()}catch(e){console.error("Error loading schema:",e),u("Error loading schema")}}function be(e,n){return n?e.filter(o=>o.name.toLowerCase().includes(n)):e}function we(e,n,o,l){let a=document.getElementById(e);a&&(a.textContent=l?`${n}/${o}`:o)}function Ge(e,n,o,l,a){let s=document.getElementById(e);if(!s)return;if(s.replaceChildren(),n.length===0){let r=document.createElement("li");r.className="list-item",r.style.opacity="0.5",r.textContent=a,s.appendChild(r);return}let i=document.createDocumentFragment();n.forEach(r=>{let d=document.createElement("li");d.className="list-item",t.selectedTable===r.name&&t.selectedTableType===o&&d.classList.add("selected"),d.dataset.name=r.name,o&&(d.dataset.type=o),d.title=r.name;let c=document.createElement("span");c.className=`item-icon codicon ${l}`,d.appendChild(c);let m=document.createElement("span");m.className="item-name",m.textContent=r.name,d.appendChild(m),i.appendChild(d)}),s.appendChild(i)}function Qt(e,n,o){let l=document.getElementById(e);if(!l)return;if(l.replaceChildren(),n.length===0){let s=document.createElement("li");s.className="list-item",s.style.opacity="0.5",s.textContent=o,l.appendChild(s);return}let a=document.createDocumentFragment();n.forEach(s=>{let i=document.createElement("li");i.className="list-item",i.title=`${s.name} on ${s.table}`;let r=document.createElement("span");r.className="item-icon codicon codicon-list-selection",i.appendChild(r);let d=document.createElement("div");d.className="item-content";let c=document.createElement("span");c.className="item-name",c.textContent=s.name,d.appendChild(c);let m=document.createElement("span");m.className="item-detail",m.textContent=s.table,d.appendChild(m),i.appendChild(d),a.appendChild(i)}),l.appendChild(a)}function Y(){let e=t.sidebarFilter.toLowerCase(),n=e.length>0,o=be(t.schemaCache.tables,e),l=be(t.schemaCache.views,e),a=be(t.schemaCache.indexes,e);we("tablesBadge",o.length,t.schemaCache.tables.length,n),we("viewsBadge",l.length,t.schemaCache.views.length,n),we("indexesBadge",a.length,t.schemaCache.indexes.length,n),Ge("tablesList",o,"table","codicon-table",e?"No matching tables":"No tables"),Ge("viewsList",l,"view","codicon-eye",e?"No matching views":"No views"),Qt("indexesList",a,e?"No matching indexes":"No indexes")}function j(){let e=document.getElementById("batchUpdateSectionTitle"),n=document.getElementById("batchUpdateList"),o=document.getElementById("batchUpdateCount"),l=document.getElementById("batchUpdateFields");if(!e||!n||!o||!l)return;let a=t.selectedCells.length;if(a===0){e.classList.add("hidden"),n.classList.add("hidden");return}e.classList.remove("hidden"),n.classList.remove("hidden"),e.classList.remove("collapsed"),o.textContent=a;let s=qe(t.selectedCells,t.tableColumns);l.replaceChildren();for(let[i,r]of s){let d=Ke(r.values),c=document.createElement("div");c.className="form-field batch-field",c.dataset.colidx=i,c.style.marginBottom="8px";let m=document.createElement("label");m.style.fontSize="11px",m.style.color="var(--text-secondary)";let h=document.createTextNode(r.name+" ");m.appendChild(h);let f=document.createElement("span");f.style.opacity="0.7",f.textContent=r.type||"",m.appendChild(f),c.appendChild(m);let p=document.createElement("div");p.style.display="flex",p.style.gap="4px";let g=document.createElement("input");g.type="text",g.className="batch-input",g.placeholder=d,g.dataset.colidx=i,g.style.flex="1",g.style.minWidth="0",p.appendChild(g);let w=document.createElement("button");w.className="btn-secondary btn-batch-null",w.style.padding="2px 6px",w.title="Set to NULL",w.textContent="NULL",p.appendChild(w);let v=document.createElement("button");v.className="btn-secondary btn-batch-patch",v.style.padding="2px 6px",v.title="JSON Patch",v.textContent="{}",p.appendChild(v),c.appendChild(p),l.appendChild(c)}}async function Zt(){if(t.selectedCells.length===0)return;let e=document.querySelectorAll(".batch-input"),n=new Map;for(let l of e){let a=parseInt(l.dataset.colidx,10);if(n.set(a,l),l.dataset.ispatch==="true")try{JSON.parse(l.value)}catch{let i=t.tableColumns[a];u(`Invalid JSON for patch in ${i.name}`);return}}let o=He(t.selectedCells,n,t.tableColumns);if(o.length===0){u("No values entered for batch update");return}try{u(`Updating ${o.length} cells...`);let l=`Batch update ${o.length} cells`,a=o.map(r=>({rowId:r.rowId,column:r.column,value:r.value,originalValue:r.originalValue,operation:r.operation}));if(await y.updateCellBatch(t.selectedTable,a,l),!o.some(r=>r.operation==="json_patch"))for(let r of o)t.gridData[r.rowIdx][r.colIdx+B()]=r.value;await I(!1);let i=[];for(let r of t.selectedCells){let d=t.gridData[r.rowIdx][r.colIdx+B()];i.push({...r,value:d})}t.selectedCells=i,j(),u("Batch update completed")}catch(l){console.error("Batch update failed:",l),u(`Batch update failed: ${l.message}`)}}function en(e){let n=document.querySelector(`.batch-input[data-colidx="${e}"]`),o=document.querySelector(`.batch-field[data-colidx="${e}"] .btn-batch-patch`);n&&(n.value="",n.placeholder="SET TO NULL",n.dataset.isnull="true",n.dataset.ispatch="false",n.style.fontStyle="italic",o&&(o.style.background="",o.style.color=""))}function tn(e,n){let o=document.querySelector(`.batch-input[data-colidx="${e}"]`);o&&(o.dataset.ispatch==="true"?(o.dataset.ispatch="false",o.placeholder="(mixed values)",n.style.background="",n.style.color=""):(o.dataset.ispatch="true",o.dataset.isnull="false",o.placeholder='JSON Patch (e.g. {"a": 1})',o.style.fontStyle="normal",n.style.background="var(--accent-color)",n.style.color="white"))}function nn(e){let n=document.getElementById(`${e}List`),o=document.querySelector(`.section-title[data-section="${e}"]`);n&&o&&(n.classList.toggle("hidden"),o.classList.toggle("collapsed"))}async function on(e,n){t.selectedTable=e,t.selectedTableType=n,t.currentPageIndex=0,t.sortedColumn=null,t.sortAscending=!0,t.filterQuery="",t.columnFilters={},t.selectedRowIds.clear(),t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear(),t.pinnedColumns.clear(),t.pinnedRowIds.clear(),t.columnWidths={},t.scrollPosition={top:0,left:0},Y();let o=document.getElementById("tableNameLabel");o&&(o.textContent=e);let l=document.getElementById("filterInput");l&&(l.value=""),await z(),await I(!0,!1),$()}async function ln(){if(t.isDbConnected)try{u("Reloading..."),await y.refreshFile(),await V(),t.selectedTable&&(await z(),await I()),u("Reloaded")}catch(e){console.error("Reload failed:",e),u(`Reload failed: ${e.message}`)}}var Q=new Set,Z=new Set;function Xe(){Q.clear(),t.selectedCells.length>0&&t.selectedCells.forEach(e=>{Q.add(`cell-${e.rowIdx}-${e.colIdx}`)}),Z.clear(),t.selectedRowIds.size>0&&document.querySelectorAll(".data-row.selected").forEach(n=>{n.id&&Z.add(n.id)})}function F(){let e=new Set;for(let o of t.selectedCells)e.add(`cell-${o.rowIdx}-${o.colIdx}`);for(let o of Q)if(!e.has(o)){let l=document.getElementById(o);l&&l.classList.remove("cell-selected")}for(let o of e)if(!Q.has(o)){let l=document.getElementById(o);l&&l.classList.add("cell-selected")}Q=e;let n=new Set;for(let o=0;oo.classList.remove("column-selected")),t.selectedColumns.size>0&&t.selectedColumns.forEach(o=>{let l=CSS.escape(o),a=document.querySelector(`.header-cell[data-column="${l}"]`);a&&a.classList.add("column-selected")})}function se(){t.selectedCells=[],t.selectedRowIds.clear(),t.selectedColumns.clear(),t.lastSelectedCell=null,F(),R(),j()}function an(){let e=document.createElement("div");return e.className="empty-view",e.innerHTML=` + `)}function R(){let e=t.selectedTable&&t.selectedTableType==="table",n=t.selectedRowIds.size>0,o=t.selectedColumns.size>0,l=document.getElementById("btnAddRow"),a=document.getElementById("btnAddColumn"),s=document.getElementById("btnDeleteRows"),i=document.getElementById("btnExport");l&&(l.disabled=!e),a&&(a.disabled=!e),s&&(s.disabled=!e||!n&&!o),i&&(i.disabled=!t.selectedTable)}function Me(){let e=document.getElementById("sidebarPanel"),n=document.getElementById("resizeHandle");if(!e||!n)return;let o=!1;n.addEventListener("mousedown",l=>{o=!0,document.body.style.cursor="col-resize",l.preventDefault()}),document.addEventListener("mousemove",l=>{if(!o)return;let a=Math.max(150,Math.min(400,l.clientX));e.style.width=a+"px"}),document.addEventListener("mouseup",()=>{o&&(o=!1,document.body.style.cursor="")})}function B(){return t.selectedTableType==="table"?1:0}function T(e,n){return t.selectedTableType==="table"?e[0]:t.currentPageIndex*t.rowsPerPage+n}function P(e,n){return e[n+B()]}function Ue(){document.addEventListener("click",e=>{let n=e.target,o=n.closest(".modal-close, .modal-cancel");if(o){let l=o.dataset.modal;l&&O(l)}n.classList.contains("modal-overlay")&&n.classList.add("hidden")}),document.addEventListener("keydown",e=>{if(e.key==="Escape"){let n=document.querySelector(".modal-overlay:not(.hidden)");n&&(n.classList.add("hidden"),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation())}})}function W(e){let n=document.getElementById(e);if(n){n.classList.remove("hidden");let o=n.querySelector("input, select, textarea, button");o&&o.focus()}}function O(e){let n=document.getElementById(e);n&&n.classList.add("hidden")}function Oe(){document.getElementById("btnAddRow")?.addEventListener("click",zt),document.getElementById("btnDeleteRows")?.addEventListener("click",jt),document.getElementById("btnAddColumn")?.addEventListener("click",Ht),document.getElementById("btnSubmitAddRow")?.addEventListener("click",Vt),document.getElementById("btnSubmitDelete")?.addEventListener("click",ae),document.getElementById("btnSubmitCreateTable")?.addEventListener("click",Kt),document.getElementById("btnAddColumnDef")?.addEventListener("click",()=>je()),document.getElementById("columnDefinitions")?.addEventListener("click",e=>{let n=e.target.closest(".btn-remove-col");if(n){let o=n.dataset.colid;qt(o)}}),document.getElementById("btnSubmitAddColumn")?.addEventListener("click",Gt)}function zt(){if(!t.selectedTable||t.selectedTableType!=="table")return;let e=document.getElementById("addRowForm");e.replaceChildren(),t.tableColumns.forEach(n=>{let o=n.notnull===1&&!n.isPrimaryKey,l=document.createElement("div");l.className="form-field";let a=document.createElement("label");if(a.textContent=n.name,o){let r=document.createElement("span");r.style.color="var(--error-color)",r.textContent="*",a.appendChild(document.createTextNode(" ")),a.appendChild(r)}let s=document.createElement("span");s.style.opacity="0.5",s.textContent=` (${n.type})`,a.appendChild(document.createTextNode(" ")),a.appendChild(s);let i=document.createElement("input");i.type="text",i.dataset.column=n.name,i.dataset.required=o.toString(),n.isPrimaryKey?(i.placeholder="Auto (Primary Key)",i.disabled=!0):o?i.placeholder="Required":i.placeholder="NULL",l.appendChild(a),l.appendChild(i),e.appendChild(l)}),W("addRowModal")}async function Vt(){let e=document.querySelectorAll("#addRowForm input[data-column]:not([disabled])"),n=[];for(let l of e){let a=l.dataset.column,s=l.value.trim();l.dataset.required==="true"&&(s===""||s.toLowerCase()==="null")?(n.push(a),l.style.borderColor="var(--error-color)"):l.style.borderColor=""}if(n.length>0){u(`Required fields missing: ${n.join(", ")}`);return}let o={};for(let l of e){let a=l.dataset.column,s=l.value.trim();s!==""&&(s.toLowerCase()==="null"?o[a]=null:!isNaN(Number(s))&&s!==""?o[a]=Number(s):o[a]=s)}try{u("Inserting row..."),await y.insertRow(t.selectedTable,o),O("addRowModal"),await I(),u("Row inserted - Ctrl+S to save")}catch(l){console.error("Insert failed:",l),u(`Error: ${l.message}`)}}function jt(){if(t.selectedColumns.size>0){let e=Array.from(t.selectedColumns);document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${e.length} column${e.length>1?"s":""} (${e.join(", ")})? This will permanently remove the column${e.length>1?"s":""} and all their data.`}else if(t.selectedRowIds.size>0)document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${t.selectedRowIds.size} row${t.selectedRowIds.size>1?"s":""}?`;else return;W("deleteModal")}async function ae(){t.selectedColumns.size>0?await _t():t.selectedRowIds.size>0&&await Wt()}async function Wt(){if(t.selectedRowIds.size===0)return;let e=Array.from(t.selectedRowIds);try{u("Deleting rows..."),await y.deleteRows(t.selectedTable,e),O("deleteModal"),t.selectedRowIds.clear(),await I(),R(),u(`Deleted ${e.length} row${e.length>1?"s":""} - Ctrl+S to save`)}catch(n){console.error("Delete rows failed:",n),u(`Error: ${n.message}`)}}async function _t(){if(t.selectedColumns.size===0)return;let e=Array.from(t.selectedColumns);try{u("Deleting columns...");let n=await y.deleteColumns(t.selectedTable,e);if(n&&n.cancelled){u("Delete cancelled"),O("deleteModal");return}O("deleteModal"),t.selectedColumns.clear(),t.selectedCells=[],t.lastSelectedCell=null,await V(),await z(),await I(),R(),u(`Deleted ${e.length} column${e.length>1?"s":""} - Ctrl+S to save`)}catch(n){console.error("Delete columns failed:",n),u(`Error: ${n.message}`)}}var ze=0;function Ve(){document.getElementById("newTableName").value="",document.getElementById("columnDefinitions").replaceChildren(),ze=0,je(!0),W("createTableModal")}function je(e=!1){let n=document.getElementById("columnDefinitions"),o=++ze,l=document.createElement("div");l.className="column-def-row",l.id=`colDef_${o}`,Object.assign(l.style,{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center"});let a=document.createElement("input");a.type="text",a.placeholder="Column name",a.className="col-name",a.style.flex="2",e&&(a.value="id"),l.appendChild(a);let s=document.createElement("select");s.className="col-type",s.style.flex="1",["INTEGER","TEXT","REAL","BLOB","NUMERIC"].forEach(f=>{let p=document.createElement("option");p.value=f,p.textContent=f,e&&f==="INTEGER"&&(p.selected=!0),!e&&f==="TEXT"&&(p.selected=!0),s.appendChild(p)}),l.appendChild(s);let i=document.createElement("label");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let r=document.createElement("input");r.type="checkbox",r.className="col-pk",r.style.margin="0",e&&(r.checked=!0),i.appendChild(r),i.appendChild(document.createTextNode(" PK")),l.appendChild(i);let d=document.createElement("label");Object.assign(d.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let c=document.createElement("input");c.type="checkbox",c.className="col-nn",c.style.margin="0",d.appendChild(c),d.appendChild(document.createTextNode(" NN")),l.appendChild(d);let m=document.createElement("button");m.className="icon-button btn-remove-col",m.dataset.colid=o.toString(),m.title="Remove",e&&(m.disabled=!0);let h=document.createElement("span");h.className="codicon codicon-close",m.appendChild(h),l.appendChild(m),n.appendChild(l)}function qt(e){let n=document.getElementById(`colDef_${e}`);n&&n.remove()}async function Kt(){let e=document.getElementById("newTableName").value.trim();if(!e){u("Error: Table name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid table name");return}let n=[],o=document.querySelectorAll(".column-def-row");for(let l of o){let a=l.querySelector(".col-name").value.trim(),s=l.querySelector(".col-type").value,i=l.querySelector(".col-pk").checked,r=l.querySelector(".col-nn").checked;a&&n.push({name:a,type:s,primaryKey:i,notNull:r})}if(n.length===0){u("Error: At least one column is required");return}try{u("Creating table..."),await y.createTable(e,n),O("createTableModal"),await V(),u(`Table "${e}" created - Ctrl+S to save`)}catch(l){console.error("Create table failed:",l),u(`Error: ${l.message}`)}}function Ht(){!t.selectedTable||t.selectedTableType!=="table"||(document.getElementById("newColumnName").value="",document.getElementById("newColumnType").value="TEXT",document.getElementById("newColumnDefault").value="",W("addColumnModal"))}async function Gt(){let e=document.getElementById("newColumnName").value.trim(),n=document.getElementById("newColumnType").value,o=document.getElementById("newColumnDefault").value.trim();if(!e){u("Error: Column name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid column name");return}try{u("Adding column..."),await y.addColumn(t.selectedTable,e,n,o),O("addColumnModal"),await z(),await I(),u(`Column "${e}" added - Ctrl+S to save`)}catch(l){console.error("Add column failed:",l),u(`Error: ${l.message}`)}}function We(){let e=document.getElementById("pragmaSettingsContainer");e&&e.addEventListener("change",n=>{let o=n.target;if(o.matches(".setting-extension")){let l=o.dataset.key,a=o.type==="checkbox"?o.checked:o.value;Xt(l,a)}else if(o.matches(".setting-pragma")){let l=o.dataset.name,a=o.dataset.type,s=o.value;a==="number"?s=Number(s):a==="bool"&&(s=s==="true"?1:0),Yt(l,s)}})}async function _e(){let e=document.getElementById("settingsModal");e&&(e.classList.remove("hidden"),await xe())}async function xe(){let e=document.getElementById("pragmaSettingsContainer");e.textContent="Loading settings...";try{let[n,o]=await Promise.all([y.getPragmas(),y.getExtensionSettings()]);Jt(n,o)}catch(n){console.error("Failed to load settings:",n),e.textContent=`Error loading settings: ${n.message}`,e.style.color="var(--error-color)"}}function Jt(e,n){let o=document.getElementById("pragmaSettingsContainer");if(!o)return;let l=(x,C)=>x.map(k=>{let L=String(k),N=String(C).toUpperCase()===L.toUpperCase(),D=document.createElement("option");return D.value=L,D.selected=N,D.textContent=L,D});o.replaceChildren();let a=x=>{let C=document.createElement("div");C.className="setting-section-title",Object.assign(C.style,{fontWeight:"600",marginBottom:"8px",paddingBottom:"4px",borderBottom:"1px solid var(--border-color)"}),C.textContent=x,o.appendChild(C)},s=(x,C,k)=>{let L=document.createElement("div");L.className="form-field";let b=document.createElement("label");if(C.type==="checkbox"?(Object.assign(b.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"}),C.style.margin="0",b.appendChild(C),b.appendChild(document.createTextNode(x)),L.appendChild(b)):(b.textContent=x,L.appendChild(b),L.appendChild(C)),k){let N=document.createElement("div");N.className="setting-desc",N.textContent=k,L.appendChild(N)}o.appendChild(L)};if(o.children.length>0){let x=document.createElement("div");x.style.height="16px",o.appendChild(x)}a("Extension Settings");let i=document.createElement("input");i.type="checkbox",i.className="setting-extension",i.dataset.key="autoCommit",i.checked=!!n.autoCommit,s("Auto-Commit Changes",i,"Automatically save changes to disk immediately. If disabled, you must save manually (Ctrl+S).");let r=document.createElement("select");r.className="setting-extension",r.dataset.key="doubleClickBehavior",l(["inline","modal","vscode"],n.cellEditBehavior).forEach(x=>r.appendChild(x)),s("Double Click Behavior",r,"Action when double-clicking a cell");let d=document.createElement("div");d.style.height="16px",o.appendChild(d),a("SQLite Settings (Pragmas)");let c=document.createElement("select");c.className="setting-pragma",c.dataset.name="journal_mode",l(["DELETE","TRUNCATE","PERSIST","MEMORY","WAL","OFF"],e.journal_mode).forEach(x=>c.appendChild(x)),s("Journal Mode",c,"Database journaling mode (WAL is recommended for concurrency)");let m=document.createElement("select");m.className="setting-pragma",m.dataset.name="foreign_keys",m.dataset.type="bool";let h=document.createElement("option");h.value="true",h.textContent="ON";let f=document.createElement("option");f.value="false",f.textContent="OFF",Number(e.foreign_keys)===1?h.selected=!0:f.selected=!0,m.appendChild(h),m.appendChild(f),s("Foreign Keys",m,"Enforce foreign key constraints");let p=document.createElement("select");p.className="setting-pragma",p.dataset.name="synchronous",p.dataset.type="number",[{v:0,t:"OFF (0)"},{v:1,t:"NORMAL (1)"},{v:2,t:"FULL (2)"},{v:3,t:"EXTRA (3)"}].forEach(x=>{let C=document.createElement("option");C.value=x.v,C.textContent=x.t,Number(e.synchronous)===x.v&&(C.selected=!0),p.appendChild(C)}),s("Synchronous",p,"Disk synchronization safety level");let g=document.createElement("select");g.className="setting-pragma",g.dataset.name="locking_mode",l(["NORMAL","EXCLUSIVE"],e.locking_mode).forEach(x=>g.appendChild(x)),s("Locking Mode",g,"");let w=document.createElement("select");w.className="setting-pragma",w.dataset.name="auto_vacuum",w.dataset.type="number",[{v:0,t:"NONE (0)"},{v:1,t:"FULL (1)"},{v:2,t:"INCREMENTAL (2)"}].forEach(x=>{let C=document.createElement("option");C.value=x.v,C.textContent=x.t,Number(e.auto_vacuum)===x.v&&(C.selected=!0),w.appendChild(C)}),s("Auto Vacuum",w,"");let v=document.createElement("input");v.type="number",v.className="setting-pragma",v.dataset.name="cache_size",v.dataset.type="number",v.value=e.cache_size,s("Cache Size",v,"Number of pages (positive) or kilobytes (negative)")}async function Xt(e,n){try{await y.updateExtensionSetting(e,n),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await xe()}}async function Yt(e,n){try{u(`Updating ${e}...`),await y.setPragma(e,n),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await xe()}}function qe(e,n){let o=new Map;for(let l of e){let a=n&&n[l.colIdx];a&&(o.has(l.colIdx)||o.set(l.colIdx,{name:a.name,type:a.type,values:new Set}),o.get(l.colIdx).values.add(l.value))}return o}function Ke(e){let n=Array.from(e||[]);if(n.length===0)return"";if(n.length>1)return"(mixed values)";let o=n[0];return o===null?"NULL":o instanceof Uint8Array?"[BLOB]":String(o)}function He(e,n,o){let l=[];for(let a of e){let s=n.get(a.colIdx);if(!s)continue;let i=s.dataset||{},r=i.isnull==="true",d=i.ispatch==="true",c=s.value;if(c===""&&!r)continue;let m=o&&o[a.colIdx];if(!m)continue;let h=c,f="set";if(r)h=null;else if(d)f="json_patch";else{let p=(m.type||"").toUpperCase();(p==="INTEGER"||p==="REAL"||p==="NUMERIC")&&!isNaN(Number(c))&&c.trim()!==""&&(h=Number(c))}l.push({rowId:a.rowId,column:m.name,value:h,originalValue:a.value,operation:f,rowIdx:a.rowIdx,colIdx:a.colIdx})}return l}function Je(){let e=document.getElementById("sidebarPanel");if(!e)return;let n=document.getElementById("sidebarFilterInput");n&&n.addEventListener("input",()=>{t.sidebarFilter=n.value,Y()}),e.addEventListener("click",o=>{let l=o.target;if(l.closest("#btnOpenSettings")){_e();return}if(l.closest("#btnOpenCreateTable")){o.stopPropagation(),Ve();return}if(l.closest("#btnReload")){ln();return}if(l.closest("#btnApplyBatchUpdate")){Zt();return}let a=l.closest(".list-item");if(a){let d=a.dataset.name,c=a.dataset.type;if(d&&c){on(d,c);return}}let s=l.closest(".section-title");if(s){if(l.closest(".icon-button")||s.id==="btnOpenSettings")return;let d=s.dataset.section;d&&nn(d)}let i=l.closest(".btn-batch-null");if(i){let d=i.closest(".batch-field");if(d){let c=parseInt(d.dataset.colidx,10);en(c)}return}let r=l.closest(".btn-batch-patch");if(r){let d=r.closest(".batch-field");if(d){let c=parseInt(d.dataset.colidx,10);tn(c,r)}return}})}async function V(){if(t.isDbConnected)try{let e=await y.fetchSchema();t.schemaCache.tables=(e.tables||[]).map(n=>({name:n.identifier})),t.schemaCache.views=(e.views||[]).map(n=>({name:n.identifier})),t.schemaCache.indexes=(e.indexes||[]).map(n=>({name:n.identifier,table:n.parentTable})),Y()}catch(e){console.error("Error loading schema:",e),u("Error loading schema")}}function be(e,n){return n?e.filter(o=>o.name.toLowerCase().includes(n)):e}function we(e,n,o,l){let a=document.getElementById(e);a&&(a.textContent=l?`${n}/${o}`:o)}function Ge(e,n,o,l,a){let s=document.getElementById(e);if(!s)return;if(s.replaceChildren(),n.length===0){let r=document.createElement("li");r.className="list-item",r.style.opacity="0.5",r.textContent=a,s.appendChild(r);return}let i=document.createDocumentFragment();n.forEach(r=>{let d=document.createElement("li");d.className="list-item",t.selectedTable===r.name&&t.selectedTableType===o&&d.classList.add("selected"),d.dataset.name=r.name,o&&(d.dataset.type=o),d.title=r.name;let c=document.createElement("span");c.className=`item-icon codicon ${l}`,d.appendChild(c);let m=document.createElement("span");m.className="item-name",m.textContent=r.name,d.appendChild(m),i.appendChild(d)}),s.appendChild(i)}function Qt(e,n,o){let l=document.getElementById(e);if(!l)return;if(l.replaceChildren(),n.length===0){let s=document.createElement("li");s.className="list-item",s.style.opacity="0.5",s.textContent=o,l.appendChild(s);return}let a=document.createDocumentFragment();n.forEach(s=>{let i=document.createElement("li");i.className="list-item",i.title=`${s.name} on ${s.table}`;let r=document.createElement("span");r.className="item-icon codicon codicon-list-selection",i.appendChild(r);let d=document.createElement("div");d.className="item-content";let c=document.createElement("span");c.className="item-name",c.textContent=s.name,d.appendChild(c);let m=document.createElement("span");m.className="item-detail",m.textContent=s.table,d.appendChild(m),i.appendChild(d),a.appendChild(i)}),l.appendChild(a)}function Y(){let e=t.sidebarFilter.toLowerCase(),n=e.length>0,o=be(t.schemaCache.tables,e),l=be(t.schemaCache.views,e),a=be(t.schemaCache.indexes,e);we("tablesBadge",o.length,t.schemaCache.tables.length,n),we("viewsBadge",l.length,t.schemaCache.views.length,n),we("indexesBadge",a.length,t.schemaCache.indexes.length,n),Ge("tablesList",o,"table","codicon-table",e?"No matching tables":"No tables"),Ge("viewsList",l,"view","codicon-eye",e?"No matching views":"No views"),Qt("indexesList",a,e?"No matching indexes":"No indexes")}function j(){let e=document.getElementById("batchUpdateSectionTitle"),n=document.getElementById("batchUpdateList"),o=document.getElementById("batchUpdateCount"),l=document.getElementById("batchUpdateFields");if(!e||!n||!o||!l)return;let a=t.selectedCells.length;if(a===0){e.classList.add("hidden"),n.classList.add("hidden");return}e.classList.remove("hidden"),n.classList.remove("hidden"),e.classList.remove("collapsed"),o.textContent=a;let s=qe(t.selectedCells,t.tableColumns);l.replaceChildren();for(let[i,r]of s){let d=Ke(r.values),c=document.createElement("div");c.className="form-field batch-field",c.dataset.colidx=i,c.style.marginBottom="8px";let m=document.createElement("label");m.style.fontSize="11px",m.style.color="var(--text-secondary)";let h=document.createTextNode(r.name+" ");m.appendChild(h);let f=document.createElement("span");f.style.opacity="0.7",f.textContent=r.type||"",m.appendChild(f),c.appendChild(m);let p=document.createElement("div");p.style.display="flex",p.style.gap="4px";let g=document.createElement("input");g.type="text",g.className="batch-input",g.placeholder=d,g.dataset.colidx=i,g.style.flex="1",g.style.minWidth="0",p.appendChild(g);let w=document.createElement("button");w.className="btn-secondary btn-batch-null",w.style.padding="2px 6px",w.title="Set to NULL",w.textContent="NULL",p.appendChild(w);let v=document.createElement("button");v.className="btn-secondary btn-batch-patch",v.style.padding="2px 6px",v.title="JSON Patch",v.textContent="{}",p.appendChild(v),c.appendChild(p),l.appendChild(c)}}async function Zt(){if(t.selectedCells.length===0)return;let e=document.querySelectorAll(".batch-input"),n=new Map;for(let l of e){let a=parseInt(l.dataset.colidx,10);if(n.set(a,l),l.dataset.ispatch==="true")try{JSON.parse(l.value)}catch{let i=t.tableColumns[a];u(`Invalid JSON for patch in ${i?.name??`column ${a}`}`);return}}let o=He(t.selectedCells,n,t.tableColumns);if(o.length===0){u("No values entered for batch update");return}try{u(`Updating ${o.length} cells...`);let l=`Batch update ${o.length} cells`,a=o.map(r=>({rowId:r.rowId,column:r.column,value:r.value,originalValue:r.originalValue,operation:r.operation}));if(await y.updateCellBatch(t.selectedTable,a,l),!o.some(r=>r.operation==="json_patch"))for(let r of o)t.gridData[r.rowIdx][r.colIdx+B()]=r.value;await I(!1);let i=[];for(let r of t.selectedCells){let d=t.gridData[r.rowIdx][r.colIdx+B()];i.push({...r,value:d})}t.selectedCells=i,j(),u("Batch update completed")}catch(l){console.error("Batch update failed:",l),u(`Batch update failed: ${l.message}`)}}function en(e){let n=document.querySelector(`.batch-input[data-colidx="${e}"]`),o=document.querySelector(`.batch-field[data-colidx="${e}"] .btn-batch-patch`);n&&(n.value="",n.placeholder="SET TO NULL",n.dataset.isnull="true",n.dataset.ispatch="false",n.style.fontStyle="italic",o&&(o.style.background="",o.style.color=""))}function tn(e,n){let o=document.querySelector(`.batch-input[data-colidx="${e}"]`);o&&(o.dataset.ispatch==="true"?(o.dataset.ispatch="false",o.placeholder="(mixed values)",n.style.background="",n.style.color=""):(o.dataset.ispatch="true",o.dataset.isnull="false",o.placeholder='JSON Patch (e.g. {"a": 1})',o.style.fontStyle="normal",n.style.background="var(--accent-color)",n.style.color="white"))}function nn(e){let n=document.getElementById(`${e}List`),o=document.querySelector(`.section-title[data-section="${e}"]`);n&&o&&(n.classList.toggle("hidden"),o.classList.toggle("collapsed"))}async function on(e,n){t.selectedTable=e,t.selectedTableType=n,t.currentPageIndex=0,t.sortedColumn=null,t.sortAscending=!0,t.filterQuery="",t.columnFilters={},t.selectedRowIds.clear(),t.selectedCells=[],t.lastSelectedCell=null,t.selectedColumns.clear(),t.pinnedColumns.clear(),t.pinnedRowIds.clear(),t.columnWidths={},t.scrollPosition={top:0,left:0},Y();let o=document.getElementById("tableNameLabel");o&&(o.textContent=e);let l=document.getElementById("filterInput");l&&(l.value=""),await z(),await I(!0,!1),$()}async function ln(){if(t.isDbConnected)try{u("Reloading..."),await y.refreshFile(),await V(),t.selectedTable&&(await z(),await I()),u("Reloaded")}catch(e){console.error("Reload failed:",e),u(`Reload failed: ${e.message}`)}}var Q=new Set,Z=new Set;function Xe(){Q.clear(),t.selectedCells.length>0&&t.selectedCells.forEach(e=>{Q.add(`cell-${e.rowIdx}-${e.colIdx}`)}),Z.clear(),t.selectedRowIds.size>0&&document.querySelectorAll(".data-row.selected").forEach(n=>{n.id&&Z.add(n.id)})}function F(){let e=new Set;for(let o of t.selectedCells)e.add(`cell-${o.rowIdx}-${o.colIdx}`);for(let o of Q)if(!e.has(o)){let l=document.getElementById(o);l&&l.classList.remove("cell-selected")}for(let o of e)if(!Q.has(o)){let l=document.getElementById(o);l&&l.classList.add("cell-selected")}Q=e;let n=new Set;for(let o=0;oo.classList.remove("column-selected")),t.selectedColumns.size>0&&t.selectedColumns.forEach(o=>{let l=CSS.escape(o),a=document.querySelector(`.header-cell[data-column="${l}"]`);a&&a.classList.add("column-selected")})}function se(){t.selectedCells=[],t.selectedRowIds.clear(),t.selectedColumns.clear(),t.lastSelectedCell=null,F(),R(),j()}function an(){let e=document.createElement("div");return e.className="empty-view",e.innerHTML=` No data This table is empty diff --git a/tests/unit/batch-update-logic.test.ts b/tests/unit/batch-update-logic.test.ts index 2410073..c205b18 100644 --- a/tests/unit/batch-update-logic.test.ts +++ b/tests/unit/batch-update-logic.test.ts @@ -118,4 +118,15 @@ describe('batch-update-logic hardening (edge cases)', () => { assert.strictEqual(u.value, 'hi'); assert.strictEqual(u.operation, 'set'); }); + it('coerces NUMERIC columns', () => { + const cols: BatchColumnDef[] = [{ name: 'qty', type: 'NUMERIC' }]; + const [u] = prepareBatchUpdates([cell(0, 0, 1)], new Map([[0, input('7')]]), cols); + assert.strictEqual(u.value, 7); + }); + it('coerces lowercase numeric column types (e.g. "integer")', () => { + const cols: BatchColumnDef[] = [{ name: 'n', type: 'integer' }]; + const [u] = prepareBatchUpdates([cell(0, 0, 1)], new Map([[0, input('42')]]), cols); + assert.strictEqual(u.value, 42); + assert.strictEqual(typeof u.value, 'number'); + }); }); diff --git a/website/public/sqlite-viewer/viewer.html b/website/public/sqlite-viewer/viewer.html index 4631ab7..30ab11c 100644 --- a/website/public/sqlite-viewer/viewer.html +++ b/website/public/sqlite-viewer/viewer.html @@ -400,7 +400,7 @@
`,a.appendChild(f)}return l.appendChild(a),l}function zt(e,t,o,l,a,s,i,r){let d=document.createElement("tbody"),c=[];for(let p=0;p({idx:h,rowId:T(p,h)})).filter(p=>n.pinnedRowIds.has(p.rowId)),...n.gridData.map((p,h)=>({idx:h,rowId:T(p,h)})).filter(p=>!n.pinnedRowIds.has(p.rowId))],f=document.createDocumentFragment();for(let{idx:p,rowId:h}of g){let b=n.gridData[p],I=n.selectedRowIds.has(h),x=n.pinnedRowIds.has(h),C=document.createElement("tr");C.id=`row-${p}`,C.className=`data-row ${I?"selected":""} ${x?"pinned":""}`,C.dataset.rowid=h,C.dataset.rowidx=p,x&&(C.style.top=`${m.get(h)}px`);let k=document.createElement("td");k.className="data-cell row-number",Object.assign(k.style,{width:`${l}px`,minWidth:`${l}px`,maxWidth:`${l}px`,position:"sticky",left:"0",zIndex:x?"8":"2"});let L=n.currentPageIndex*n.rowsPerPage+p+1;k.appendChild(document.createTextNode(String(L)));let w=document.createElement("span");w.className=`pin-icon codicon codicon-pin ${x?"pinned":""}`,w.title=x?"Unpin row":"Pin row",k.appendChild(w),C.appendChild(k);for(let D=0;Dw&&w.trim()!=="");if(r.innerHTML="",n.gridData.length===0&&!f&&n.tableColumns.length===0){r.appendChild(Ut());return}let p=new Set;if(n.selectedCells.length>0)for(let w of n.selectedCells)p.add(`${w.rowIdx},${w.colIdx}`);let h=document.createElement("table");if(h.className="data-grid",Object.keys(n.columnWidths).length===0&&n.gridData.length>0)for(let w of n.tableColumns){let D=w.name.length,N=w.isPrimaryKey?86:70,W=D*8+N;n.columnWidths[w.name]=Math.max(80,Math.min(250,W))}let b=[...n.tableColumns.filter(w=>n.pinnedColumns.has(w.name)),...n.tableColumns.filter(w=>!n.pinnedColumns.has(w.name))],I=new Map,x=i-1;for(let w of b)n.pinnedColumns.has(w.name)&&(I.set(w.name,x),x+=n.columnWidths[w.name]||120);let C=new Map;n.tableColumns.forEach((w,D)=>C.set(w.name,D));let k=Ot(i,b,I);h.appendChild(k);let L=zt(b,C,I,i,52,26,p,f);h.appendChild(L),r.appendChild(h),r.scrollLeft=m,r.scrollTop=g,Fe()}function Ue(){document.getElementById("pageIndicator").textContent=`${n.currentPageIndex+1} / ${n.totalPageCount}`,document.getElementById("btnFirst").disabled=n.currentPageIndex===0,document.getElementById("btnPrev").disabled=n.currentPageIndex===0,document.getElementById("btnNext").disabled=n.currentPageIndex>=n.totalPageCount-1,document.getElementById("btnLast").disabled=n.currentPageIndex>=n.totalPageCount-1}async function K(){if(n.selectedTable)try{let e=await y.getTableInfo(n.selectedTable);n.tableColumns=e.map(o=>({cid:o.ordinal,name:o.identifier,type:o.declaredType,notnull:o.isRequired,dflt_value:o.defaultExpression,isPrimaryKey:o.primaryKeyPosition>0})).sort((o,l)=>o.cid-l.cid);let t=new Set(n.tableColumns.map(o=>o.name));n.sortedColumn&&!t.has(n.sortedColumn)&&(n.sortedColumn=null,n.sortAscending=!0);for(let o of Object.keys(n.columnFilters))t.has(o)||delete n.columnFilters[o]}catch(e){console.error("Error loading columns:",e),u("Error loading columns")}}async function v(e=!0,t=!0){if(!n.selectedTable)return;let o=document.getElementById("gridContainer");t&&o&&o.querySelector(".data-grid")&&(n.scrollPosition.left=o.scrollLeft,n.scrollPosition.top=o.scrollTop),e&&(n.isLoadingData=!0,$e()),R();try{let l=[];for(let[m,g]of Object.entries(n.columnFilters))g&&g.trim()&&l.push({column:m,value:g});let a={filters:l,globalFilter:n.filterQuery,columns:n.tableColumns.map(m=>m.name)};n.totalRecordCount=await y.fetchTableCount(n.selectedTable,a),n.totalPageCount=Math.max(1,Math.ceil(n.totalRecordCount/n.rowsPerPage)),n.currentPageIndex>=n.totalPageCount&&(n.currentPageIndex=Math.max(0,n.totalPageCount-1));let s=n.selectedTableType==="table",i=n.tableColumns.map(m=>m.name),d={columns:s?["rowid",...i]:i,orderBy:n.sortedColumn,orderDir:n.sortAscending?"ASC":"DESC",limit:n.rowsPerPage,offset:n.currentPageIndex*n.rowsPerPage,filters:l,globalFilter:n.filterQuery},c=await y.fetchTableData(n.selectedTable,d);n.gridData=c.rows||[],!e&&o&&o.querySelector(".data-grid")&&(n.scrollPosition.left=o.scrollLeft,n.scrollPosition.top=o.scrollTop),!e&&n.editingCellInfo||z(n.scrollPosition.top,n.scrollPosition.left),o&&(o.scrollLeft=n.scrollPosition.left,o.scrollTop=n.scrollPosition.top),Ue(),u(`${n.totalRecordCount} records`)}catch(l){console.error("Error loading data:",l),u(`Error: ${l.message}`),ne(l.message)}finally{e&&(n.isLoadingData=!1)}}var S={PNG:[137,80,78,71,13,10,26,10],JPEG:[255,216,255],GIF:[71,73,70,56],BMP:[66,77],RIFF:[82,73,70,70],WEBP:[87,69,66,80],PDF:[37,80,68,70,45],ID3:[73,68,51],MP3_SYNC1:[255,251],MP3_SYNC2:[255,243],MP3_SYNC3:[255,242],OGG:[79,103,103,83],WAVE:[87,65,86,69],FLAC:[102,76,97,67],FTYP:[102,116,121,112],WEBM:[26,69,223,163],AVI:[65,86,73,32]},le=class{constructor(){this.currentObjectUrl=null,this.modal=document.getElementById("blob-inspector-modal"),this.previewContainer=document.getElementById("tab-preview"),this.hexContainer=document.querySelector(".hex-dump"),this.infoContainer=document.getElementById("blob-info"),this.currentData=null,this.currentType=null,this.currentRowId=null,this.currentColName=null,this.currentCellInfo=null,this.isUploading=!1,this.setupEventListeners()}setupEventListeners(){this.modal.querySelectorAll(".modal-close").forEach(l=>{l.addEventListener("click",()=>this.close())}),this.modal.querySelectorAll(".tab-btn").forEach(l=>{l.addEventListener("click",a=>{let s=a.target.dataset.tab;this.switchTab(s)})});let t=document.getElementById("blob-download-btn");t&&t.addEventListener("click",()=>this.download());let o=document.getElementById("blob-replace-btn");o&&o.addEventListener("click",()=>this.handleReplace())}setUploadState(t){this.isUploading=t;let o=document.getElementById("blob-replace-btn"),l=document.getElementById("blob-download-btn");o&&(o.disabled=t,o.textContent=t?"Uploading...":"Replace"),l&&(l.disabled=t)}async handleReplace(){if(!this.isUploading)try{if(((await y.getExtensionSettings())?.fileOperations||"native")==="web")this.showFileInput();else{let l=await y.selectFile();if(l){let a=l.data;if(!(a instanceof Uint8Array)){if(Array.isArray(a))a=new Uint8Array(a);else if(a&&typeof a=="object"){let i=Object.keys(a).filter(r=>!isNaN(parseInt(r,10))).sort((r,d)=>parseInt(r,10)-parseInt(d,10)).map(r=>a[r]);a=new Uint8Array(i)}}let s={name:l.name,arrayBuffer:async()=>a.buffer};await this.uploadFile(s)}}}catch(t){console.error("Replace failed:",t),u(`Replace failed: ${t.message}`)}}showFileInput(){let t=document.createElement("input");t.type="file",t.onchange=async o=>{let l=o.target.files[0];l&&await this.uploadFile(l)},t.click()}async uploadFile(t){if(!(!this.currentRowId||!this.currentColName)&&!this.isUploading){this.setUploadState(!0);try{u(`Reading ${t.name}...`);let o=await t.arrayBuffer(),l=new Uint8Array(o),a=l.length/(1024*1024),s=50;if(a>s)throw new Error(`File too large (${a.toFixed(1)}MB). Maximum size is ${s}MB to prevent freezing.`);a>10?u(`Uploading ${t.name} (${a.toFixed(1)}MB - this may take a moment)...`):u(`Uploading ${t.name}...`);let{rowIdx:i,colIdx:r}=this.currentCellInfo,d=this.currentData;await y.updateCell(n.selectedTable,this.currentRowId,this.currentColName,l,d),n.gridData&&n.gridData[i]&&(n.gridData[i][r+B()]=l),this.inspect(l,this.currentRowId,this.currentColName,i,r),u(`Replaced with ${t.name}`)}catch(o){console.error("Replace failed:",o);let l=o.message||String(o);l.includes("timeout")&&(l="Upload timed out. Try a smaller file or increase the timeout."),u(`Replace failed: ${l}`)}finally{this.setUploadState(!1)}}}close(){this.modal.classList.add("hidden"),this.cleanup()}cleanup(){this.setUploadState(!1),this.currentObjectUrl&&(URL.revokeObjectURL(this.currentObjectUrl),this.currentObjectUrl=null),this.previewContainer.innerHTML="",this.hexContainer.value="",this.infoContainer.textContent="",this.currentData=null}switchTab(t){this.modal.querySelectorAll(".tab-btn").forEach(a=>{a.dataset.tab===t?(a.classList.add("active"),a.style.borderBottom="2px solid var(--accent-color)",a.style.color="var(--text-primary)"):(a.classList.remove("active"),a.style.borderBottom="none",a.style.color="var(--text-secondary)")});let o=document.getElementById("tab-preview"),l=document.getElementById("tab-hex");t==="preview"?(o.style.display="flex",l.style.display="none"):(o.style.display="none",l.style.display="block")}async download(){if(!this.currentData)return;let t=this.currentType?.ext||"bin",o=`blob_${this.currentRowId}.${t}`;try{((await y.getExtensionSettings())?.fileOperations||"native")==="web"?(this.downloadBlob(this.currentData,o),u(`Downloaded ${o}`)):(await y.saveFile(o,this.currentData),u(`Saved ${o}`))}catch(l){console.error("Download failed:",l),u(`Download failed: ${l.message}`)}}downloadBlob(t,o){let l=new Blob([t]),a=URL.createObjectURL(l),s=document.createElement("a");s.href=a,s.download=o,s.click(),URL.revokeObjectURL(a)}inspect(t,o,l,a,s){this.cleanup(),this.currentRowId=o,this.currentColName=l,this.currentCellInfo={rowIdx:a,colIdx:s},this.modal.classList.remove("hidden"),this.switchTab("preview");let i=t instanceof Uint8Array?t:new Uint8Array(t);this.currentData=i;let r=this.detectType(i);this.currentType=r;let d=this.formatSize(i.length);this.infoContainer.textContent=`${l} (Row ${o}) | ${r.mime||"Unknown Type"} | ${d}`,this.renderPreview(i,r),this.renderHex(i)}detectType(t){if(this.checkSignature(t,S.PNG))return{mime:"image/png",type:"image",ext:"png"};if(this.checkSignature(t,S.JPEG))return{mime:"image/jpeg",type:"image",ext:"jpg"};if(this.checkSignature(t,S.GIF))return{mime:"image/gif",type:"image",ext:"gif"};if(this.checkSignature(t,S.BMP))return{mime:"image/bmp",type:"image",ext:"bmp"};if(this.checkSignature(t,S.RIFF)&&this.checkSignature(t.subarray(8),S.WEBP))return{mime:"image/webp",type:"image",ext:"webp"};if(this.checkSignature(t,S.PDF))return{mime:"application/pdf",type:"pdf",ext:"pdf"};if(this.checkSignature(t,S.ID3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(t,S.MP3_SYNC1)||this.checkSignature(t,S.MP3_SYNC2)||this.checkSignature(t,S.MP3_SYNC3))return{mime:"audio/mpeg",type:"audio",ext:"mp3"};if(this.checkSignature(t,S.OGG))return{mime:"audio/ogg",type:"audio",ext:"ogg"};if(this.checkSignature(t,S.RIFF)&&this.checkSignature(t.subarray(8),S.WAVE))return{mime:"audio/wav",type:"audio",ext:"wav"};if(this.checkSignature(t,S.FLAC))return{mime:"audio/flac",type:"audio",ext:"flac"};if(this.checkSignature(t.subarray(4),S.FTYP)){let o=String.fromCharCode(...t.subarray(8,12));return o.startsWith("mp4")||o==="isom"||o==="avc1"||o==="M4V "?{mime:"video/mp4",type:"video",ext:"mp4"}:o==="qt "||o.startsWith("M4A")?{mime:"video/quicktime",type:"video",ext:"mov"}:{mime:"video/mp4",type:"video",ext:"mp4"}}if(this.checkSignature(t,S.WEBM))return{mime:"video/webm",type:"video",ext:"webm"};if(this.checkSignature(t,S.RIFF)&&this.checkSignature(t.subarray(8),S.AVI))return{mime:"video/avi",type:"video",ext:"avi"};if(this.isText(t)){try{let o=new TextDecoder().decode(t),l=JSON.parse(o);if(typeof l=="object"&&l!==null)return{mime:"application/json",type:"json",ext:"json"}}catch{}return{mime:"text/plain",type:"text",ext:"txt"}}return{mime:"application/octet-stream",type:"binary",ext:"bin"}}checkSignature(t,o){if(t.lengththis.download()),l.appendChild(a),l.appendChild(s),l.appendChild(i),this.previewContainer.appendChild(l)}else{let l=document.createElement("div");l.className="empty-view";let a=document.createElement("span");a.className="codicon codicon-file-binary",a.style.fontSize="48px",a.style.opacity="0.5";let s=document.createElement("span");s.style.marginTop="12px",s.textContent="Binary Data";let i=document.createElement("span");i.style.fontSize="12px",i.style.opacity="0.7",i.textContent="Use Hex view to inspect",l.appendChild(a),l.appendChild(s),l.appendChild(i),this.previewContainer.appendChild(l)}}renderHex(t){if(!this.hexContainer)return;let o=16*1e3,l="",a=t.subarray(0,o);for(let s=0;s=32&&p<=126?String.fromCharCode(p):".")}else r.push(" "),d.push(" ");let c=r.slice(0,8).join(" "),m=r.slice(8).join(" "),g=d.join("");l+=`${i} ${c} ${m} |${g}| `}t.length>o&&(l+=` -... (${(t.length-o).toLocaleString()} more bytes not shown)`),this.hexContainer.value=l}formatSize(t){if(t===0)return"0 B";let o=1024,l=["B","KB","MB","GB"],a=Math.floor(Math.log(t)/Math.log(o));return parseFloat((t/Math.pow(o,a)).toFixed(2))+" "+l[a]}};var we;function Oe(){we=new le,document.getElementById("btnCloseCellPreview")?.addEventListener("click",H),document.getElementById("formatJsonBtn")?.addEventListener("click",jt),document.getElementById("compactJsonBtn")?.addEventListener("click",Vt),document.getElementById("wrapTextBtn")?.addEventListener("click",Wt),document.getElementById("openInVsCodeBtn")?.addEventListener("click",be),document.getElementById("btnCancelCellPreview")?.addEventListener("click",H),document.getElementById("cellPreviewSaveBtn")?.addEventListener("click",Ke)}function ze(e,t,o){if(n.selectedTableType!=="table"){u("Views are read-only");return}if(n.editingCellInfo){if(n.editingCellInfo.rowIdx===e&&n.editingCellInfo.colIdx===t)return;se()}let l=n.tableColumns[t];if(!l)return;let a=document.getElementById(`cell-${e}-${t}`);if(!a)return;let s=n.gridData[e],i=P(s,t);if(i instanceof Uint8Array){q(e,t,o);return}if(typeof i=="string"){let c=i.trim();if(c.startsWith("{")&&c.endsWith("}")||c.startsWith("[")&&c.endsWith("]"))try{JSON.parse(c),q(e,t,o);return}catch{}}n.editingCellInfo={rowIdx:e,colIdx:t,rowId:o,columnName:l.name,originalValue:i};let r=i===null?"":String(i);a.innerHTML="",a.classList.add("editing");let d=document.createElement("textarea");d.className="cell-input",d.value=r,d.spellcheck=!1,a.appendChild(d),d.focus(),n.activeCellInput=d,d.addEventListener("keydown",je),d.addEventListener("blur",Ve),d.addEventListener("click",c=>c.stopPropagation()),n.isTransitioningEdit=!0,setTimeout(()=>{n.isTransitioningEdit=!1},100)}function je(e){e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),We()):e.key==="Escape"&&(e.preventDefault(),se())}function Ve(){setTimeout(()=>{n.editingCellInfo&&We()},100)}async function We(){if(n.isSavingCell||!n.editingCellInfo||!n.activeCellInput)return;let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.editingCellInfo,s=n.activeCellInput.value,i=a===null?"":String(a);if(s===i){se(),n.selectedCells=[],n.lastSelectedCell=null,M();return}let r=n.tableColumns[t],d=r&&r.notnull===1,c;s===""?d?c="":c=null:!isNaN(Number(s))&&s.trim()!==""?c=Number(s):c=s;try{n.isSavingCell=!0,u("Saving..."),await y.updateCell(n.selectedTable,te(o),l,c,a),n.gridData[e][t+B()]=c,_e(),Ee(e,t,c),n.selectedCells=[],n.lastSelectedCell=null,M(),u("Saved")}catch(m){console.error("Save failed:",m);let g=m.message||String(m);u(`Save failed: ${g}`)}finally{n.isSavingCell=!1}}function se(){if(!n.editingCellInfo)return;let{rowIdx:e,colIdx:t,originalValue:o}=n.editingCellInfo;_e(),Ee(e,t,o),oe()}function _e(){n.activeCellInput&&(n.activeCellInput.removeEventListener("keydown",je),n.activeCellInput.removeEventListener("blur",Ve),n.activeCellInput=null),n.editingCellInfo=null}async function be(){if(!n.cellPreviewInfo)return;let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.cellPreviewInfo,s=n.tableColumns[t],i=document.getElementById("vscode-env")?.dataset.webviewId||"default";try{u("Opening in VS Code..."),H(),await y.openCellEditor({table:n.selectedTable,name:""},te(o),l,{},{value:a,type:{type:s.type},webviewId:i,rowCount:n.gridData.length}),u("Opened in VS Code")}catch(r){console.error("Failed to open in VS Code:",r),u(`Error: ${r.message}`)}}function q(e,t,o){n.editingCellInfo&&se();let l=n.tableColumns[t];if(!l)return;let a=n.gridData[e];if(!a)return;let s=P(a,t);if(s instanceof Uint8Array){we&&we.inspect(s,o,l.name,e,t);return}n.cellPreviewInfo={rowIdx:e,colIdx:t,rowId:o,columnName:l.name,originalValue:s};let i=document.getElementById("cellPreviewModal"),r=document.getElementById("cellPreviewColumnName"),d=document.getElementById("cellPreviewTypeBadge"),c=document.getElementById("cellPreviewTextarea"),m=document.getElementById("cellPreviewReadonlyBadge"),g=document.getElementById("cellPreviewSaveBtn"),f=document.getElementById("wrapTextBtn");r.textContent=l.name,d.textContent=l.type||"TEXT";let p="";s==null?p="":s instanceof Uint8Array?p="[BLOB: "+Array.from(s).map(b=>b.toString(16).padStart(2,"0")).join(" ")+"]":p=String(s),c.value=p;let h=n.selectedTableType!=="table";c.readOnly=h,h?(c.classList.add("readonly"),m.style.display="inline",g.style.display="none"):(c.classList.remove("readonly"),m.style.display="none",g.style.display="inline-block"),ae(),c.style.whiteSpace=n.cellPreviewWrapEnabled?"pre-wrap":"pre",c.style.overflowX=n.cellPreviewWrapEnabled?"hidden":"auto",f.classList.toggle("active",n.cellPreviewWrapEnabled),i.classList.remove("hidden"),c.focus(),c.oninput=ae,c.onkeydown=b=>{b.key==="Escape"?(b.preventDefault(),H()):b.key==="Enter"&&(b.ctrlKey||b.metaKey)&&(b.preventDefault(),Ke())}}function ae(){let e=document.getElementById("cellPreviewTextarea"),t=document.getElementById("cellPreviewCharCount"),o=e.value.length;t.textContent=`${o.toLocaleString()} character${o!==1?"s":""}`}function H(){document.getElementById("cellPreviewModal").classList.add("hidden"),n.cellPreviewInfo=null}async function Ke(){if(!n.cellPreviewInfo)return;if(n.selectedTableType!=="table"){u("Views are read-only");return}let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.cellPreviewInfo,i=document.getElementById("cellPreviewTextarea").value,r=a===null?"":String(a);if(i===r){H(),n.selectedCells=[],n.lastSelectedCell=null,M();return}let d=n.tableColumns[t],c=d&&d.notnull===1,m;i===""?m=c?"":null:!isNaN(Number(i))&&i.trim()!==""?m=Number(i):m=i;try{u("Saving..."),await y.updateCell(n.selectedTable,te(o),l,m,a),n.gridData[e][t+B()]=m,H(),Ee(e,t,m),n.selectedCells=[],n.lastSelectedCell=null,M(),u("Saved")}catch(g){console.error("Save failed:",g),u(`Save failed: ${g.message}`)}}function jt(){let e=document.getElementById("cellPreviewTextarea");try{let t=JSON.parse(e.value);e.value=JSON.stringify(t,null,2),ae()}catch{u("Content is not valid JSON")}}function Vt(){let e=document.getElementById("cellPreviewTextarea");try{let t=JSON.parse(e.value);e.value=JSON.stringify(t),ae()}catch{u("Content is not valid JSON")}}function Wt(){n.cellPreviewWrapEnabled=!n.cellPreviewWrapEnabled;let e=document.getElementById("cellPreviewTextarea"),t=document.getElementById("wrapTextBtn");e.style.whiteSpace=n.cellPreviewWrapEnabled?"pre-wrap":"pre",e.style.overflowX=n.cellPreviewWrapEnabled?"hidden":"auto",t.classList.toggle("active",n.cellPreviewWrapEnabled)}function Ee(e,t,o){let l=document.getElementById(`cell-${e}-${t}`);if(!l)return;l.classList.remove("editing"),o==null?l.classList.add("null-value"):l.classList.remove("null-value");let a=n.tableColumns[t],s=_(o,a?.type,n.dateFormat,a?.name),i=o!=null&&!(o instanceof Uint8Array);l.textContent="";let r=document.createElement("span");if(r.className="cell-text",r.textContent=s,l.appendChild(r),i){let c=document.createElement("span");c.className="expand-icon codicon codicon-link-external",c.title="View full content",l.appendChild(c)}let d=r.scrollWidth>r.clientWidth;l.classList.toggle("has-overflow",d)}function qe(){clearTimeout(n.filterTimer),n.filterTimer=setTimeout(()=>{n.filterQuery=document.getElementById("filterInput").value,n.currentPageIndex=0,v(),$()},300)}function He(){n.rowsPerPage=parseInt(document.getElementById("pageSizeSelect").value,10),n.currentPageIndex=0,v(),$()}function Ge(){let e=document.getElementById("dateFormatSelect");e&&(n.dateFormat=e.value,z(),$())}function Z(e){e>=0&&el.name===t);if(o!==-1){if((e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),n.selectedRowIds.clear(),e.shiftKey&&n.lastSelectedColumnIndex!==null){e.metaKey||e.ctrlKey||(n.selectedCells=[],n.selectedColumns.clear());let l=Math.min(n.lastSelectedColumnIndex,o),a=Math.max(n.lastSelectedColumnIndex,o),s=new Array;if(n.selectedCells.length>0)for(let i of n.selectedCells)i.colIdx>=l&&i.colIdx<=a&&(s[i.rowIdx]||(s[i.rowIdx]=new Set),s[i.rowIdx].add(i.colIdx));for(let i=l;i<=a;i++){let r=n.tableColumns[i].name;n.selectedColumns.add(r);for(let d=0;d0&&a===l)n.selectedCells=n.selectedCells.filter(i=>i.colIdx!==o),n.selectedColumns.delete(t);else{let i=new Set;for(let r of n.selectedCells)r.colIdx===o&&i.add(r.rowIdx);for(let r=0;r0&&a===l&&n.selectedColumns.size===1&&n.selectedColumns.has(t))n.selectedCells=[],n.selectedColumns.clear(),n.lastSelectedColumnIndex=null;else{n.selectedCells=[],n.selectedColumns.clear();for(let i=0;ii.name===n.resizingColumn);if(l===-1)return;let a=document.querySelector(`th[data-column="${n.resizingColumn}"]`);a&&(a.style.width=`${o}px`,a.style.minWidth=`${o}px`,a.style.maxWidth=`${o}px`);let s=document.querySelectorAll(`.data-row td:nth-child(${l+2})`);for(let i of s)i.style.width=`${o}px`,i.style.minWidth=`${o}px`,i.style.maxWidth=`${o}px`;n.pinnedColumns.has(n.resizingColumn)}function nt(){if(!n.resizingColumn)return;let e=document.querySelector(".resize-handle.resizing");e&&e.classList.remove("resizing"),n.resizingColumn=null,document.removeEventListener("mousemove",tt),document.removeEventListener("mouseup",nt),document.body.style.userSelect="",document.body.style.cursor="",z()}function ot(e,t,o){if(e.stopPropagation(),(e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),e.shiftKey&&n.lastSelectedRowIndex!==null){e.metaKey||e.ctrlKey||n.selectedRowIds.clear();let l=Math.min(n.lastSelectedRowIndex,o),a=Math.max(n.lastSelectedRowIndex,o);for(let s=l;s<=a;s++){let i=T(n.gridData[s],s);n.selectedRowIds.add(i)}}else e.ctrlKey||e.metaKey?(n.selectedRowIds.has(t)?n.selectedRowIds.delete(t):n.selectedRowIds.add(t),n.lastSelectedRowIndex=o):n.selectedRowIds.has(t)&&n.selectedRowIds.size===1?(n.selectedRowIds.delete(t),n.lastSelectedRowIndex=null):(n.selectedRowIds.clear(),n.selectedRowIds.add(t),n.lastSelectedRowIndex=o);M(),R(),O()}function ie(e){if(e.stopPropagation(),n.gridData.length===0)return;n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear();let t=!0;for(let o=0;o=s&&m.rowIdx<=i&&m.colIdx>=r&&m.colIdx<=d&&(c[m.rowIdx]||(c[m.rowIdx]=new Set),c[m.rowIdx].add(m.colIdx));for(let m=s;m<=i;m++){let g=c[m];for(let f=r;f<=d;f++)if(!g||!g.has(f)){let p=T(n.gridData[m],m),h=P(n.gridData[m],f);n.selectedCells.push({rowIdx:m,colIdx:f,rowId:p,value:h})}}}else if(e.metaKey||e.ctrlKey){e.preventDefault(),n.selectedRowIds.clear();let s=n.selectedCells.findIndex(i=>i.rowIdx===t&&i.colIdx===o);s>=0?n.selectedCells.splice(s,1):(n.selectedCells.push({rowIdx:t,colIdx:o,rowId:l,value:a}),n.lastSelectedCell={rowIdx:t,colIdx:o})}else if(e.shiftKey&&n.lastSelectedCell){e.preventDefault(),n.selectedRowIds.clear(),n.selectedCells=[];let s=Math.min(n.lastSelectedCell.rowIdx,t),i=Math.max(n.lastSelectedCell.rowIdx,t),r=Math.min(n.lastSelectedCell.colIdx,o),d=Math.max(n.lastSelectedCell.colIdx,o);for(let c=s;c<=i;c++)for(let m=r;m<=d;m++){let g=T(n.gridData[c],c),f=P(n.gridData[c],m);n.selectedCells.push({rowIdx:c,colIdx:m,rowId:g,value:f})}}else n.selectedRowIds.clear(),n.selectedCells=[{rowIdx:t,colIdx:o,rowId:l,value:a}],n.lastSelectedCell={rowIdx:t,colIdx:o},n.selectedColumns.clear();M(),R(),O()}function at(e,t,o,l){if(n.cellEditBehavior==="vscode"){let a=n.tableColumns[o];if(!a)return;let s=n.gridData[t];if(!s)return;let i=P(s,o);n.cellPreviewInfo={rowIdx:t,colIdx:o,rowId:l,columnName:a.name,originalValue:i},be()}else n.cellEditBehavior==="modal"?q(t,o,l):ze(t,o,l)}function st(){document.getElementById("filterInput")?.addEventListener("keyup",qe),document.getElementById("pageSizeSelect")?.addEventListener("change",He),document.getElementById("dateFormatSelect")?.addEventListener("change",Ge),document.getElementById("btnFirst")?.addEventListener("click",()=>Z(0)),document.getElementById("btnPrev")?.addEventListener("click",()=>Z(n.currentPageIndex-1)),document.getElementById("btnNext")?.addEventListener("click",()=>Z(n.currentPageIndex+1)),document.getElementById("btnLast")?.addEventListener("click",()=>Z(n.totalPageCount-1))}function it(){let e=document.getElementById("gridContainer");e&&(e.addEventListener("mousedown",_t),e.addEventListener("keydown",Kt),e.addEventListener("click",qt),e.addEventListener("dblclick",Jt),e.addEventListener("mouseover",Xt),e.addEventListener("scroll",Yt,{passive:!0}))}function _t(e){if(e.target.classList.contains("resize-handle")){e.stopPropagation();let t=e.target.closest(".header-cell");t&&t.dataset.column&&et(e,t.dataset.column)}}function Kt(e){if(e.target.classList.contains("column-filter")){let t=e.target.dataset.column;t&&Xe(e,t)}}function qt(e){let t=e.target;if(t.closest(".grid-header")){Ht(e,t);return}Gt(e,t)}function Ht(e,t){if(t.closest(".filter-apply-btn")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Ie(l.dataset.column);return}if(t.closest(".header-bottom")||t.closest(".column-filter")){e.stopPropagation();return}if(t.closest(".select-column-icon")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Ye(e,l.dataset.column);return}if(t.closest(".pin-icon")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Ze(e,l.dataset.column);return}if(t.closest(".row-number-header")){ie(e);return}let o=t.closest(".header-top");if(o){let l=o.closest(".header-cell");l&&l.dataset.column&&Je(l.dataset.column);return}}function Gt(e,t){if(t.closest(".pin-icon")){let l=t.closest(".data-row");if(l){let a=l.dataset.rowid,s=Q(a);Qe(e,s)}return}if(t.closest(".expand-icon")){let l=t.closest(".data-cell");if(l){let a=parseInt(l.dataset.rowidx,10),s=parseInt(l.dataset.colidx,10),i=Q(l.closest(".data-row").dataset.rowid);q(a,s,i)}return}if(t.closest(".row-number")){let l=t.closest(".data-row");if(l){let a=Q(l.dataset.rowid),s=parseInt(l.dataset.rowidx,10);ot(e,a,s)}return}let o=t.closest(".data-cell");if(o){let l=parseInt(o.dataset.rowidx,10),a=parseInt(o.dataset.colidx,10),s=o.closest(".data-row"),i=Q(s.dataset.rowid);lt(e,l,a,i);return}}function Jt(e){let t=e.target.closest(".data-cell");if(t&&!t.classList.contains("row-number")){let o=parseInt(t.dataset.rowidx,10),l=parseInt(t.dataset.colidx,10),a=t.closest(".data-row"),s=Q(a.dataset.rowid);at(e,o,l,s)}}function Xt(e){let t=e.target.closest(".data-cell");if(t&&!t.classList.contains("checked-overflow")){let o=t.querySelector(".cell-text");if(o){let l=o.scrollWidth>o.clientWidth;t.classList.toggle("has-overflow",l),t.classList.add("checked-overflow")}}}function Yt(e){let t=e.currentTarget;n.scrollPosition.left=t.scrollLeft,n.scrollPosition.top=t.scrollTop,$()}function Q(e){if(e==null)return e;let t=Number(e);return!isNaN(t)&&e.trim()!==""?t:e}function rt(){document.addEventListener("click",e=>{let t=e.target,o=t.closest(".modal-close, .modal-cancel");if(o){let l=o.dataset.modal;l&&U(l)}t.classList.contains("modal-overlay")&&t.classList.add("hidden")}),document.addEventListener("keydown",e=>{if(e.key==="Escape"){let t=document.querySelector(".modal-overlay:not(.hidden)");t&&(t.classList.add("hidden"),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation())}})}function j(e){let t=document.getElementById(e);if(t){t.classList.remove("hidden");let o=t.querySelector("input, select, textarea, button");o&&o.focus()}}function U(e){let t=document.getElementById(e);t&&t.classList.add("hidden")}function ct(){document.getElementById("btnAddRow")?.addEventListener("click",Zt),document.getElementById("btnDeleteRows")?.addEventListener("click",en),document.getElementById("btnAddColumn")?.addEventListener("click",an),document.getElementById("btnSubmitAddRow")?.addEventListener("click",Qt),document.getElementById("btnSubmitDelete")?.addEventListener("click",re),document.getElementById("btnSubmitCreateTable")?.addEventListener("click",ln),document.getElementById("btnAddColumnDef")?.addEventListener("click",()=>mt()),document.getElementById("columnDefinitions")?.addEventListener("click",e=>{let t=e.target.closest(".btn-remove-col");if(t){let o=t.dataset.colid;on(o)}}),document.getElementById("btnSubmitAddColumn")?.addEventListener("click",sn)}function Zt(){if(!n.selectedTable||n.selectedTableType!=="table")return;let e=document.getElementById("addRowForm");e.replaceChildren(),n.tableColumns.forEach(t=>{let o=t.notnull===1&&!t.isPrimaryKey,l=document.createElement("div");l.className="form-field";let a=document.createElement("label");if(a.textContent=t.name,o){let r=document.createElement("span");r.style.color="var(--error-color)",r.textContent="*",a.appendChild(document.createTextNode(" ")),a.appendChild(r)}let s=document.createElement("span");s.style.opacity="0.5",s.textContent=` (${t.type})`,a.appendChild(document.createTextNode(" ")),a.appendChild(s);let i=document.createElement("input");i.type="text",i.dataset.column=t.name,i.dataset.required=o.toString(),t.isPrimaryKey?(i.placeholder="Auto (Primary Key)",i.disabled=!0):o?i.placeholder="Required":i.placeholder="NULL",l.appendChild(a),l.appendChild(i),e.appendChild(l)}),j("addRowModal")}async function Qt(){let e=document.querySelectorAll("#addRowForm input[data-column]:not([disabled])"),t=[];for(let l of e){let a=l.dataset.column,s=l.value.trim();l.dataset.required==="true"&&(s===""||s.toLowerCase()==="null")?(t.push(a),l.style.borderColor="var(--error-color)"):l.style.borderColor=""}if(t.length>0){u(`Required fields missing: ${t.join(", ")}`);return}let o={};for(let l of e){let a=l.dataset.column,s=l.value.trim();s!==""&&(s.toLowerCase()==="null"?o[a]=null:!isNaN(Number(s))&&s!==""?o[a]=Number(s):o[a]=s)}try{u("Inserting row..."),await y.insertRow(n.selectedTable,o),U("addRowModal"),await v(),u("Row inserted - Ctrl+S to save")}catch(l){console.error("Insert failed:",l),u(`Error: ${l.message}`)}}function en(){if(n.selectedColumns.size>0){let e=Array.from(n.selectedColumns);document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${e.length} column${e.length>1?"s":""} (${e.join(", ")})? This will permanently remove the column${e.length>1?"s":""} and all their data.`}else if(n.selectedRowIds.size>0)document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${n.selectedRowIds.size} row${n.selectedRowIds.size>1?"s":""}?`;else return;j("deleteModal")}async function re(){n.selectedColumns.size>0?await nn():n.selectedRowIds.size>0&&await tn()}async function tn(){if(n.selectedRowIds.size===0)return;let e=Array.from(n.selectedRowIds);try{u("Deleting rows..."),await y.deleteRows(n.selectedTable,e),U("deleteModal"),n.selectedRowIds.clear(),await v(),R(),u(`Deleted ${e.length} row${e.length>1?"s":""} - Ctrl+S to save`)}catch(t){console.error("Delete rows failed:",t),u(`Error: ${t.message}`)}}async function nn(){if(n.selectedColumns.size===0)return;let e=Array.from(n.selectedColumns);try{u("Deleting columns...");let t=await y.deleteColumns(n.selectedTable,e);if(t&&t.cancelled){u("Delete cancelled"),U("deleteModal");return}U("deleteModal"),n.selectedColumns.clear(),n.selectedCells=[],n.lastSelectedCell=null,await V(),await K(),await v(),R(),u(`Deleted ${e.length} column${e.length>1?"s":""} - Ctrl+S to save`)}catch(t){console.error("Delete columns failed:",t),u(`Error: ${t.message}`)}}var dt=0;function ut(){document.getElementById("newTableName").value="",document.getElementById("columnDefinitions").replaceChildren(),dt=0,mt(!0),j("createTableModal")}function mt(e=!1){let t=document.getElementById("columnDefinitions"),o=++dt,l=document.createElement("div");l.className="column-def-row",l.id=`colDef_${o}`,Object.assign(l.style,{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center"});let a=document.createElement("input");a.type="text",a.placeholder="Column name",a.className="col-name",a.style.flex="2",e&&(a.value="id"),l.appendChild(a);let s=document.createElement("select");s.className="col-type",s.style.flex="1",["INTEGER","TEXT","REAL","BLOB","NUMERIC"].forEach(f=>{let p=document.createElement("option");p.value=f,p.textContent=f,e&&f==="INTEGER"&&(p.selected=!0),!e&&f==="TEXT"&&(p.selected=!0),s.appendChild(p)}),l.appendChild(s);let i=document.createElement("label");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let r=document.createElement("input");r.type="checkbox",r.className="col-pk",r.style.margin="0",e&&(r.checked=!0),i.appendChild(r),i.appendChild(document.createTextNode(" PK")),l.appendChild(i);let d=document.createElement("label");Object.assign(d.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let c=document.createElement("input");c.type="checkbox",c.className="col-nn",c.style.margin="0",d.appendChild(c),d.appendChild(document.createTextNode(" NN")),l.appendChild(d);let m=document.createElement("button");m.className="icon-button btn-remove-col",m.dataset.colid=o.toString(),m.title="Remove",e&&(m.disabled=!0);let g=document.createElement("span");g.className="codicon codicon-close",m.appendChild(g),l.appendChild(m),t.appendChild(l)}function on(e){let t=document.getElementById(`colDef_${e}`);t&&t.remove()}async function ln(){let e=document.getElementById("newTableName").value.trim();if(!e){u("Error: Table name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid table name");return}let t=[],o=document.querySelectorAll(".column-def-row");for(let l of o){let a=l.querySelector(".col-name").value.trim(),s=l.querySelector(".col-type").value,i=l.querySelector(".col-pk").checked,r=l.querySelector(".col-nn").checked;a&&t.push({name:a,type:s,primaryKey:i,notNull:r})}if(t.length===0){u("Error: At least one column is required");return}try{u("Creating table..."),await y.createTable(e,t),U("createTableModal"),await V(),u(`Table "${e}" created - Ctrl+S to save`)}catch(l){console.error("Create table failed:",l),u(`Error: ${l.message}`)}}function an(){!n.selectedTable||n.selectedTableType!=="table"||(document.getElementById("newColumnName").value="",document.getElementById("newColumnType").value="TEXT",document.getElementById("newColumnDefault").value="",j("addColumnModal"))}async function sn(){let e=document.getElementById("newColumnName").value.trim(),t=document.getElementById("newColumnType").value,o=document.getElementById("newColumnDefault").value.trim();if(!e){u("Error: Column name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid column name");return}try{u("Adding column..."),await y.addColumn(n.selectedTable,e,t,o),U("addColumnModal"),await K(),await v(),u(`Column "${e}" added - Ctrl+S to save`)}catch(l){console.error("Add column failed:",l),u(`Error: ${l.message}`)}}function pt(){let e=document.getElementById("pragmaSettingsContainer");e&&e.addEventListener("change",t=>{let o=t.target;if(o.matches(".setting-extension")){let l=o.dataset.key,a=o.type==="checkbox"?o.checked:o.value;cn(l,a)}else if(o.matches(".setting-pragma")){let l=o.dataset.name,a=o.dataset.type,s=o.value;a==="number"?s=Number(s):a==="bool"&&(s=s==="true"?1:0),dn(l,s)}})}async function ft(){let e=document.getElementById("settingsModal");e&&(e.classList.remove("hidden"),await ve())}async function ve(){let e=document.getElementById("pragmaSettingsContainer");e.textContent="Loading settings...";try{let[t,o]=await Promise.all([y.getPragmas(),y.getExtensionSettings()]);rn(t,o)}catch(t){console.error("Failed to load settings:",t),e.textContent=`Error loading settings: ${t.message}`,e.style.color="var(--error-color)"}}function rn(e,t){let o=document.getElementById("pragmaSettingsContainer");if(!o)return;let l=(x,C)=>x.map(k=>{let L=String(k),D=String(C).toUpperCase()===L.toUpperCase(),N=document.createElement("option");return N.value=L,N.selected=D,N.textContent=L,N});o.replaceChildren();let a=x=>{let C=document.createElement("div");C.className="setting-section-title",Object.assign(C.style,{fontWeight:"600",marginBottom:"8px",paddingBottom:"4px",borderBottom:"1px solid var(--border-color)"}),C.textContent=x,o.appendChild(C)},s=(x,C,k)=>{let L=document.createElement("div");L.className="form-field";let w=document.createElement("label");if(C.type==="checkbox"?(Object.assign(w.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"}),C.style.margin="0",w.appendChild(C),w.appendChild(document.createTextNode(x)),L.appendChild(w)):(w.textContent=x,L.appendChild(w),L.appendChild(C)),k){let D=document.createElement("div");D.className="setting-desc",D.textContent=k,L.appendChild(D)}o.appendChild(L)};if(o.children.length>0){let x=document.createElement("div");x.style.height="16px",o.appendChild(x)}a("Extension Settings");let i=document.createElement("input");i.type="checkbox",i.className="setting-extension",i.dataset.key="autoCommit",i.checked=!!t.autoCommit,s("Auto-Commit Changes",i,"Automatically save changes to disk immediately. If disabled, you must save manually (Ctrl+S).");let r=document.createElement("select");r.className="setting-extension",r.dataset.key="doubleClickBehavior",l(["inline","modal","vscode"],t.cellEditBehavior).forEach(x=>r.appendChild(x)),s("Double Click Behavior",r,"Action when double-clicking a cell");let d=document.createElement("div");d.style.height="16px",o.appendChild(d),a("SQLite Settings (Pragmas)");let c=document.createElement("select");c.className="setting-pragma",c.dataset.name="journal_mode",l(["DELETE","TRUNCATE","PERSIST","MEMORY","WAL","OFF"],e.journal_mode).forEach(x=>c.appendChild(x)),s("Journal Mode",c,"Database journaling mode (WAL is recommended for concurrency)");let m=document.createElement("select");m.className="setting-pragma",m.dataset.name="foreign_keys",m.dataset.type="bool";let g=document.createElement("option");g.value="true",g.textContent="ON";let f=document.createElement("option");f.value="false",f.textContent="OFF",Number(e.foreign_keys)===1?g.selected=!0:f.selected=!0,m.appendChild(g),m.appendChild(f),s("Foreign Keys",m,"Enforce foreign key constraints");let p=document.createElement("select");p.className="setting-pragma",p.dataset.name="synchronous",p.dataset.type="number",[{v:0,t:"OFF (0)"},{v:1,t:"NORMAL (1)"},{v:2,t:"FULL (2)"},{v:3,t:"EXTRA (3)"}].forEach(x=>{let C=document.createElement("option");C.value=x.v,C.textContent=x.t,Number(e.synchronous)===x.v&&(C.selected=!0),p.appendChild(C)}),s("Synchronous",p,"Disk synchronization safety level");let h=document.createElement("select");h.className="setting-pragma",h.dataset.name="locking_mode",l(["NORMAL","EXCLUSIVE"],e.locking_mode).forEach(x=>h.appendChild(x)),s("Locking Mode",h,"");let b=document.createElement("select");b.className="setting-pragma",b.dataset.name="auto_vacuum",b.dataset.type="number",[{v:0,t:"NONE (0)"},{v:1,t:"FULL (1)"},{v:2,t:"INCREMENTAL (2)"}].forEach(x=>{let C=document.createElement("option");C.value=x.v,C.textContent=x.t,Number(e.auto_vacuum)===x.v&&(C.selected=!0),b.appendChild(C)}),s("Auto Vacuum",b,"");let I=document.createElement("input");I.type="number",I.className="setting-pragma",I.dataset.name="cache_size",I.dataset.type="number",I.value=e.cache_size,s("Cache Size",I,"Number of pages (positive) or kilobytes (negative)")}async function cn(e,t){try{await y.updateExtensionSetting(e,t),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await ve()}}async function dn(e,t){try{u(`Updating ${e}...`),await y.setPragma(e,t),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await ve()}}function ht(e,t){let o=new Map;for(let l of e){let a=t&&t[l.colIdx];a&&(o.has(l.colIdx)||o.set(l.colIdx,{name:a.name,type:a.type,values:new Set}),o.get(l.colIdx).values.add(l.value))}return o}function gt(e){let t=Array.from(e||[]);if(t.length===0)return"";if(t.length>1)return"(mixed values)";let o=t[0];return o===null?"NULL":o instanceof Uint8Array?"[BLOB]":String(o)}function yt(e,t,o){let l=[];for(let a of e){let s=t.get(a.colIdx);if(!s)continue;let i=s.dataset||{},r=i.isnull==="true",d=i.ispatch==="true",c=s.value;if(c===""&&!r)continue;let m=o&&o[a.colIdx];if(!m)continue;let g=c,f="set";r?g=null:d?f="json_patch":(m.type==="INTEGER"||m.type==="REAL"||m.type==="NUMERIC")&&!isNaN(Number(c))&&c.trim()!==""&&(g=Number(c)),l.push({rowId:a.rowId,column:m.name,value:g,originalValue:a.value,operation:f,rowIdx:a.rowIdx,colIdx:a.colIdx})}return l}function xt(){let e=document.getElementById("sidebarPanel");if(!e)return;let t=document.getElementById("sidebarFilterInput");t&&t.addEventListener("input",()=>{n.sidebarFilter=t.value,Be()}),e.addEventListener("click",o=>{let l=o.target;if(l.closest("#btnOpenSettings")){ft();return}if(l.closest("#btnOpenCreateTable")){o.stopPropagation(),ut();return}if(l.closest("#btnReload")){yn();return}if(l.closest("#btnApplyBatchUpdate")){mn();return}let a=l.closest(".list-item");if(a){let d=a.dataset.name,c=a.dataset.type;if(d&&c){gn(d,c);return}}let s=l.closest(".section-title");if(s){if(l.closest(".icon-button")||s.id==="btnOpenSettings")return;let d=s.dataset.section;d&&hn(d)}let i=l.closest(".btn-batch-null");if(i){let d=i.closest(".batch-field");if(d){let c=parseInt(d.dataset.colidx,10);pn(c)}return}let r=l.closest(".btn-batch-patch");if(r){let d=r.closest(".batch-field");if(d){let c=parseInt(d.dataset.colidx,10);fn(c,r)}return}})}async function V(){if(n.isDbConnected)try{let e=await y.fetchSchema();n.schemaCache.tables=(e.tables||[]).map(t=>({name:t.identifier})),n.schemaCache.views=(e.views||[]).map(t=>({name:t.identifier})),n.schemaCache.indexes=(e.indexes||[]).map(t=>({name:t.identifier,table:t.parentTable})),Be()}catch(e){console.error("Error loading schema:",e),u("Error loading schema")}}function Se(e,t){return t?e.filter(o=>o.name.toLowerCase().includes(t)):e}function Te(e,t,o,l){let a=document.getElementById(e);a&&(a.textContent=l?`${t}/${o}`:o)}function Ct(e,t,o,l,a){let s=document.getElementById(e);if(!s)return;if(s.replaceChildren(),t.length===0){let r=document.createElement("li");r.className="list-item",r.style.opacity="0.5",r.textContent=a,s.appendChild(r);return}let i=document.createDocumentFragment();t.forEach(r=>{let d=document.createElement("li");d.className="list-item",n.selectedTable===r.name&&n.selectedTableType===o&&d.classList.add("selected"),d.dataset.name=r.name,o&&(d.dataset.type=o),d.title=r.name;let c=document.createElement("span");c.className=`item-icon codicon ${l}`,d.appendChild(c);let m=document.createElement("span");m.className="item-name",m.textContent=r.name,d.appendChild(m),i.appendChild(d)}),s.appendChild(i)}function un(e,t,o){let l=document.getElementById(e);if(!l)return;if(l.replaceChildren(),t.length===0){let s=document.createElement("li");s.className="list-item",s.style.opacity="0.5",s.textContent=o,l.appendChild(s);return}let a=document.createDocumentFragment();t.forEach(s=>{let i=document.createElement("li");i.className="list-item",i.title=`${s.name} on ${s.table}`;let r=document.createElement("span");r.className="item-icon codicon codicon-list-selection",i.appendChild(r);let d=document.createElement("div");d.className="item-content";let c=document.createElement("span");c.className="item-name",c.textContent=s.name,d.appendChild(c);let m=document.createElement("span");m.className="item-detail",m.textContent=s.table,d.appendChild(m),i.appendChild(d),a.appendChild(i)}),l.appendChild(a)}function Be(){let e=n.sidebarFilter.toLowerCase(),t=e.length>0,o=Se(n.schemaCache.tables,e),l=Se(n.schemaCache.views,e),a=Se(n.schemaCache.indexes,e);Te("tablesBadge",o.length,n.schemaCache.tables.length,t),Te("viewsBadge",l.length,n.schemaCache.views.length,t),Te("indexesBadge",a.length,n.schemaCache.indexes.length,t),Ct("tablesList",o,"table","codicon-table",e?"No matching tables":"No tables"),Ct("viewsList",l,"view","codicon-eye",e?"No matching views":"No views"),un("indexesList",a,e?"No matching indexes":"No indexes")}function O(){let e=document.getElementById("batchUpdateSectionTitle"),t=document.getElementById("batchUpdateList"),o=document.getElementById("batchUpdateCount"),l=document.getElementById("batchUpdateFields");if(!e||!t||!o||!l)return;let a=n.selectedCells.length;if(a===0){e.classList.add("hidden"),t.classList.add("hidden");return}e.classList.remove("hidden"),t.classList.remove("hidden"),e.classList.remove("collapsed"),o.textContent=a;let s=ht(n.selectedCells,n.tableColumns);l.replaceChildren();for(let[i,r]of s){let d=gt(r.values),c=document.createElement("div");c.className="form-field batch-field",c.dataset.colidx=i,c.style.marginBottom="8px";let m=document.createElement("label");m.style.fontSize="11px",m.style.color="var(--text-secondary)";let g=document.createTextNode(r.name+" ");m.appendChild(g);let f=document.createElement("span");f.style.opacity="0.7",f.textContent=r.type||"",m.appendChild(f),c.appendChild(m);let p=document.createElement("div");p.style.display="flex",p.style.gap="4px";let h=document.createElement("input");h.type="text",h.className="batch-input",h.placeholder=d,h.dataset.colidx=i,h.style.flex="1",h.style.minWidth="0",p.appendChild(h);let b=document.createElement("button");b.className="btn-secondary btn-batch-null",b.style.padding="2px 6px",b.title="Set to NULL",b.textContent="NULL",p.appendChild(b);let I=document.createElement("button");I.className="btn-secondary btn-batch-patch",I.style.padding="2px 6px",I.title="JSON Patch",I.textContent="{}",p.appendChild(I),c.appendChild(p),l.appendChild(c)}}async function mn(){if(n.selectedCells.length===0)return;let e=document.querySelectorAll(".batch-input"),t=new Map;for(let l of e){let a=parseInt(l.dataset.colidx,10);if(t.set(a,l),l.dataset.ispatch==="true")try{JSON.parse(l.value)}catch{let i=n.tableColumns[a];u(`Invalid JSON for patch in ${i.name}`);return}}let o=yt(n.selectedCells,t,n.tableColumns);if(o.length===0){u("No values entered for batch update");return}try{u(`Updating ${o.length} cells...`);let l=`Batch update ${o.length} cells`,a=o.map(r=>({rowId:r.rowId,column:r.column,value:r.value,originalValue:r.originalValue,operation:r.operation}));if(await y.updateCellBatch(n.selectedTable,a,l),!o.some(r=>r.operation==="json_patch"))for(let r of o)n.gridData[r.rowIdx][r.colIdx+B()]=r.value;await v(!1);let i=[];for(let r of n.selectedCells){let d=n.gridData[r.rowIdx][r.colIdx+B()];i.push({...r,value:d})}n.selectedCells=i,O(),u("Batch update completed")}catch(l){console.error("Batch update failed:",l),u(`Batch update failed: ${l.message}`)}}function pn(e){let t=document.querySelector(`.batch-input[data-colidx="${e}"]`),o=document.querySelector(`.batch-field[data-colidx="${e}"] .btn-batch-patch`);t&&(t.value="",t.placeholder="SET TO NULL",t.dataset.isnull="true",t.dataset.ispatch="false",t.style.fontStyle="italic",o&&(o.style.background="",o.style.color=""))}function fn(e,t){let o=document.querySelector(`.batch-input[data-colidx="${e}"]`);o&&(o.dataset.ispatch==="true"?(o.dataset.ispatch="false",o.placeholder="(mixed values)",t.style.background="",t.style.color=""):(o.dataset.ispatch="true",o.dataset.isnull="false",o.placeholder='JSON Patch (e.g. {"a": 1})',o.style.fontStyle="normal",t.style.background="var(--accent-color)",t.style.color="white"))}function hn(e){let t=document.getElementById(`${e}List`),o=document.querySelector(`.section-title[data-section="${e}"]`);t&&o&&(t.classList.toggle("hidden"),o.classList.toggle("collapsed"))}async function gn(e,t){n.selectedTable=e,n.selectedTableType=t,n.currentPageIndex=0,n.sortedColumn=null,n.sortAscending=!0,n.filterQuery="",n.columnFilters={},n.selectedRowIds.clear(),n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),n.pinnedColumns.clear(),n.pinnedRowIds.clear(),n.columnWidths={},n.scrollPosition={top:0,left:0},Be();let o=document.getElementById("tableNameLabel");o&&(o.textContent=e);let l=document.getElementById("filterInput");l&&(l.value=""),await K(),await v(!0,!1),$()}async function yn(){if(n.isDbConnected)try{u("Reloading..."),await y.refreshFile(),await V(),n.selectedTable&&(await K(),await v()),u("Reloaded")}catch(e){console.error("Reload failed:",e),u(`Reload failed: ${e.message}`)}}function wt(){document.getElementById("btnExport")?.addEventListener("click",Cn),document.getElementById("btnSubmitExport")?.addEventListener("click",xn),document.getElementById("exportFormat")?.addEventListener("change",bt)}function Cn(){if(!n.selectedTable)return;let e=document.getElementById("exportFormat");e&&(e.value="csv");let t=document.getElementById("exportColumns");t&&(t.replaceChildren(),n.tableColumns.forEach(o=>{let l=document.createElement("div"),a=document.createElement("label");Object.assign(a.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let s=document.createElement("input");s.type="checkbox",s.className="export-col-check",s.value=o.name,s.checked=!0,s.style.margin="0",a.appendChild(s),a.appendChild(document.createTextNode(o.name)),t.appendChild(a)})),bt(),j("exportModal")}function bt(){let e=document.getElementById("exportFormat").value,t=document.getElementById("exportOptions");if(t.replaceChildren(),e==="csv"||e==="excel"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportHeader",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Headers")),t.appendChild(o)}else if(e==="sql"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportTableName",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Table Name")),t.appendChild(o)}}async function xn(){let e=document.getElementById("exportFormat").value,t=document.querySelectorAll(".export-col-check:checked"),o=Array.from(t).map(a=>a.value);if(o.length===0){u("Error: Select at least one column");return}let l={};if(e==="csv"||e==="excel"?l.header=document.getElementById("exportHeader")?.checked??!0:e==="sql"&&(l.includeTableName=document.getElementById("exportTableName")?.checked??!0),n.selectedTableType==="table"){let a=Array.from(n.selectedRowIds);a.length>0&&(l.rowIds=a)}try{u("Exporting..."),U("exportModal"),await y.exportTable({table:n.selectedTable},o,null,null,{format:e,...l}),u("Export initiated")}catch(a){console.error("Export failed:",a),u(`Export failed: ${a.message}`)}}async function Et(){if(n.selectedCells.length!==0)try{let e;if(n.selectedCells.length===1){let t=n.selectedCells[0].value;t==null?e="":t instanceof Uint8Array?e="[BLOB]":e=String(t)}else{let t=[...new Set(n.selectedCells.map(s=>s.rowIdx))].sort((s,i)=>s-i),o=[...new Set(n.selectedCells.map(s=>s.colIdx))].sort((s,i)=>s-i),l=new Map;for(let s of n.selectedCells)l.set(`${s.rowIdx},${s.colIdx}`,s.value);let a=[];for(let s of t){let i=[];for(let r of o){let d=`${s},${r}`,c=l.has(d)?l.get(d):"";c==null?c="":c instanceof Uint8Array?c="[BLOB]":(c=String(c),c=c.replace(/\t/g," ").replace(/\n/g," ")),i.push(c)}a.push(i.join(" "))}e=a.join(` +... (${(t.length-o).toLocaleString()} more bytes not shown)`),this.hexContainer.value=l}formatSize(t){if(t===0)return"0 B";let o=1024,l=["B","KB","MB","GB"],a=Math.floor(Math.log(t)/Math.log(o));return parseFloat((t/Math.pow(o,a)).toFixed(2))+" "+l[a]}};var we;function Oe(){we=new le,document.getElementById("btnCloseCellPreview")?.addEventListener("click",H),document.getElementById("formatJsonBtn")?.addEventListener("click",jt),document.getElementById("compactJsonBtn")?.addEventListener("click",Vt),document.getElementById("wrapTextBtn")?.addEventListener("click",Wt),document.getElementById("openInVsCodeBtn")?.addEventListener("click",be),document.getElementById("btnCancelCellPreview")?.addEventListener("click",H),document.getElementById("cellPreviewSaveBtn")?.addEventListener("click",Ke)}function ze(e,t,o){if(n.selectedTableType!=="table"){u("Views are read-only");return}if(n.editingCellInfo){if(n.editingCellInfo.rowIdx===e&&n.editingCellInfo.colIdx===t)return;se()}let l=n.tableColumns[t];if(!l)return;let a=document.getElementById(`cell-${e}-${t}`);if(!a)return;let s=n.gridData[e],i=P(s,t);if(i instanceof Uint8Array){q(e,t,o);return}if(typeof i=="string"){let c=i.trim();if(c.startsWith("{")&&c.endsWith("}")||c.startsWith("[")&&c.endsWith("]"))try{JSON.parse(c),q(e,t,o);return}catch{}}n.editingCellInfo={rowIdx:e,colIdx:t,rowId:o,columnName:l.name,originalValue:i};let r=i===null?"":String(i);a.innerHTML="",a.classList.add("editing");let d=document.createElement("textarea");d.className="cell-input",d.value=r,d.spellcheck=!1,a.appendChild(d),d.focus(),n.activeCellInput=d,d.addEventListener("keydown",je),d.addEventListener("blur",Ve),d.addEventListener("click",c=>c.stopPropagation()),n.isTransitioningEdit=!0,setTimeout(()=>{n.isTransitioningEdit=!1},100)}function je(e){e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),We()):e.key==="Escape"&&(e.preventDefault(),se())}function Ve(){setTimeout(()=>{n.editingCellInfo&&We()},100)}async function We(){if(n.isSavingCell||!n.editingCellInfo||!n.activeCellInput)return;let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.editingCellInfo,s=n.activeCellInput.value,i=a===null?"":String(a);if(s===i){se(),n.selectedCells=[],n.lastSelectedCell=null,M();return}let r=n.tableColumns[t],d=r&&r.notnull===1,c;s===""?d?c="":c=null:!isNaN(Number(s))&&s.trim()!==""?c=Number(s):c=s;try{n.isSavingCell=!0,u("Saving..."),await y.updateCell(n.selectedTable,te(o),l,c,a),n.gridData[e][t+B()]=c,_e(),Ee(e,t,c),n.selectedCells=[],n.lastSelectedCell=null,M(),u("Saved")}catch(m){console.error("Save failed:",m);let g=m.message||String(m);u(`Save failed: ${g}`)}finally{n.isSavingCell=!1}}function se(){if(!n.editingCellInfo)return;let{rowIdx:e,colIdx:t,originalValue:o}=n.editingCellInfo;_e(),Ee(e,t,o),oe()}function _e(){n.activeCellInput&&(n.activeCellInput.removeEventListener("keydown",je),n.activeCellInput.removeEventListener("blur",Ve),n.activeCellInput=null),n.editingCellInfo=null}async function be(){if(!n.cellPreviewInfo)return;let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.cellPreviewInfo,s=n.tableColumns[t],i=document.getElementById("vscode-env")?.dataset.webviewId||"default";try{u("Opening in VS Code..."),H(),await y.openCellEditor({table:n.selectedTable,name:""},te(o),l,{},{value:a,type:{type:s.type},webviewId:i,rowCount:n.gridData.length}),u("Opened in VS Code")}catch(r){console.error("Failed to open in VS Code:",r),u(`Error: ${r.message}`)}}function q(e,t,o){n.editingCellInfo&&se();let l=n.tableColumns[t];if(!l)return;let a=n.gridData[e];if(!a)return;let s=P(a,t);if(s instanceof Uint8Array){we&&we.inspect(s,o,l.name,e,t);return}n.cellPreviewInfo={rowIdx:e,colIdx:t,rowId:o,columnName:l.name,originalValue:s};let i=document.getElementById("cellPreviewModal"),r=document.getElementById("cellPreviewColumnName"),d=document.getElementById("cellPreviewTypeBadge"),c=document.getElementById("cellPreviewTextarea"),m=document.getElementById("cellPreviewReadonlyBadge"),g=document.getElementById("cellPreviewSaveBtn"),f=document.getElementById("wrapTextBtn");r.textContent=l.name,d.textContent=l.type||"TEXT";let p="";s==null?p="":s instanceof Uint8Array?p="[BLOB: "+Array.from(s).map(b=>b.toString(16).padStart(2,"0")).join(" ")+"]":p=String(s),c.value=p;let h=n.selectedTableType!=="table";c.readOnly=h,h?(c.classList.add("readonly"),m.style.display="inline",g.style.display="none"):(c.classList.remove("readonly"),m.style.display="none",g.style.display="inline-block"),ae(),c.style.whiteSpace=n.cellPreviewWrapEnabled?"pre-wrap":"pre",c.style.overflowX=n.cellPreviewWrapEnabled?"hidden":"auto",f.classList.toggle("active",n.cellPreviewWrapEnabled),i.classList.remove("hidden"),c.focus(),c.oninput=ae,c.onkeydown=b=>{b.key==="Escape"?(b.preventDefault(),H()):b.key==="Enter"&&(b.ctrlKey||b.metaKey)&&(b.preventDefault(),Ke())}}function ae(){let e=document.getElementById("cellPreviewTextarea"),t=document.getElementById("cellPreviewCharCount"),o=e.value.length;t.textContent=`${o.toLocaleString()} character${o!==1?"s":""}`}function H(){document.getElementById("cellPreviewModal").classList.add("hidden"),n.cellPreviewInfo=null}async function Ke(){if(!n.cellPreviewInfo)return;if(n.selectedTableType!=="table"){u("Views are read-only");return}let{rowIdx:e,colIdx:t,rowId:o,columnName:l,originalValue:a}=n.cellPreviewInfo,i=document.getElementById("cellPreviewTextarea").value,r=a===null?"":String(a);if(i===r){H(),n.selectedCells=[],n.lastSelectedCell=null,M();return}let d=n.tableColumns[t],c=d&&d.notnull===1,m;i===""?m=c?"":null:!isNaN(Number(i))&&i.trim()!==""?m=Number(i):m=i;try{u("Saving..."),await y.updateCell(n.selectedTable,te(o),l,m,a),n.gridData[e][t+B()]=m,H(),Ee(e,t,m),n.selectedCells=[],n.lastSelectedCell=null,M(),u("Saved")}catch(g){console.error("Save failed:",g),u(`Save failed: ${g.message}`)}}function jt(){let e=document.getElementById("cellPreviewTextarea");try{let t=JSON.parse(e.value);e.value=JSON.stringify(t,null,2),ae()}catch{u("Content is not valid JSON")}}function Vt(){let e=document.getElementById("cellPreviewTextarea");try{let t=JSON.parse(e.value);e.value=JSON.stringify(t),ae()}catch{u("Content is not valid JSON")}}function Wt(){n.cellPreviewWrapEnabled=!n.cellPreviewWrapEnabled;let e=document.getElementById("cellPreviewTextarea"),t=document.getElementById("wrapTextBtn");e.style.whiteSpace=n.cellPreviewWrapEnabled?"pre-wrap":"pre",e.style.overflowX=n.cellPreviewWrapEnabled?"hidden":"auto",t.classList.toggle("active",n.cellPreviewWrapEnabled)}function Ee(e,t,o){let l=document.getElementById(`cell-${e}-${t}`);if(!l)return;l.classList.remove("editing"),o==null?l.classList.add("null-value"):l.classList.remove("null-value");let a=n.tableColumns[t],s=_(o,a?.type,n.dateFormat,a?.name),i=o!=null&&!(o instanceof Uint8Array);l.textContent="";let r=document.createElement("span");if(r.className="cell-text",r.textContent=s,l.appendChild(r),i){let c=document.createElement("span");c.className="expand-icon codicon codicon-link-external",c.title="View full content",l.appendChild(c)}let d=r.scrollWidth>r.clientWidth;l.classList.toggle("has-overflow",d)}function qe(){clearTimeout(n.filterTimer),n.filterTimer=setTimeout(()=>{n.filterQuery=document.getElementById("filterInput").value,n.currentPageIndex=0,v(),$()},300)}function He(){n.rowsPerPage=parseInt(document.getElementById("pageSizeSelect").value,10),n.currentPageIndex=0,v(),$()}function Ge(){let e=document.getElementById("dateFormatSelect");e&&(n.dateFormat=e.value,z(),$())}function Z(e){e>=0&&el.name===t);if(o!==-1){if((e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),n.selectedRowIds.clear(),e.shiftKey&&n.lastSelectedColumnIndex!==null){e.metaKey||e.ctrlKey||(n.selectedCells=[],n.selectedColumns.clear());let l=Math.min(n.lastSelectedColumnIndex,o),a=Math.max(n.lastSelectedColumnIndex,o),s=new Array;if(n.selectedCells.length>0)for(let i of n.selectedCells)i.colIdx>=l&&i.colIdx<=a&&(s[i.rowIdx]||(s[i.rowIdx]=new Set),s[i.rowIdx].add(i.colIdx));for(let i=l;i<=a;i++){let r=n.tableColumns[i].name;n.selectedColumns.add(r);for(let d=0;d0&&a===l)n.selectedCells=n.selectedCells.filter(i=>i.colIdx!==o),n.selectedColumns.delete(t);else{let i=new Set;for(let r of n.selectedCells)r.colIdx===o&&i.add(r.rowIdx);for(let r=0;r0&&a===l&&n.selectedColumns.size===1&&n.selectedColumns.has(t))n.selectedCells=[],n.selectedColumns.clear(),n.lastSelectedColumnIndex=null;else{n.selectedCells=[],n.selectedColumns.clear();for(let i=0;ii.name===n.resizingColumn);if(l===-1)return;let a=document.querySelector(`th[data-column="${n.resizingColumn}"]`);a&&(a.style.width=`${o}px`,a.style.minWidth=`${o}px`,a.style.maxWidth=`${o}px`);let s=document.querySelectorAll(`.data-row td:nth-child(${l+2})`);for(let i of s)i.style.width=`${o}px`,i.style.minWidth=`${o}px`,i.style.maxWidth=`${o}px`;n.pinnedColumns.has(n.resizingColumn)}function nt(){if(!n.resizingColumn)return;let e=document.querySelector(".resize-handle.resizing");e&&e.classList.remove("resizing"),n.resizingColumn=null,document.removeEventListener("mousemove",tt),document.removeEventListener("mouseup",nt),document.body.style.userSelect="",document.body.style.cursor="",z()}function ot(e,t,o){if(e.stopPropagation(),(e.shiftKey||e.metaKey||e.ctrlKey)&&e.preventDefault(),n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),e.shiftKey&&n.lastSelectedRowIndex!==null){e.metaKey||e.ctrlKey||n.selectedRowIds.clear();let l=Math.min(n.lastSelectedRowIndex,o),a=Math.max(n.lastSelectedRowIndex,o);for(let s=l;s<=a;s++){let i=T(n.gridData[s],s);n.selectedRowIds.add(i)}}else e.ctrlKey||e.metaKey?(n.selectedRowIds.has(t)?n.selectedRowIds.delete(t):n.selectedRowIds.add(t),n.lastSelectedRowIndex=o):n.selectedRowIds.has(t)&&n.selectedRowIds.size===1?(n.selectedRowIds.delete(t),n.lastSelectedRowIndex=null):(n.selectedRowIds.clear(),n.selectedRowIds.add(t),n.lastSelectedRowIndex=o);M(),R(),O()}function ie(e){if(e.stopPropagation(),n.gridData.length===0)return;n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear();let t=!0;for(let o=0;o=s&&m.rowIdx<=i&&m.colIdx>=r&&m.colIdx<=d&&(c[m.rowIdx]||(c[m.rowIdx]=new Set),c[m.rowIdx].add(m.colIdx));for(let m=s;m<=i;m++){let g=c[m];for(let f=r;f<=d;f++)if(!g||!g.has(f)){let p=T(n.gridData[m],m),h=P(n.gridData[m],f);n.selectedCells.push({rowIdx:m,colIdx:f,rowId:p,value:h})}}}else if(e.metaKey||e.ctrlKey){e.preventDefault(),n.selectedRowIds.clear();let s=n.selectedCells.findIndex(i=>i.rowIdx===t&&i.colIdx===o);s>=0?n.selectedCells.splice(s,1):(n.selectedCells.push({rowIdx:t,colIdx:o,rowId:l,value:a}),n.lastSelectedCell={rowIdx:t,colIdx:o})}else if(e.shiftKey&&n.lastSelectedCell){e.preventDefault(),n.selectedRowIds.clear(),n.selectedCells=[];let s=Math.min(n.lastSelectedCell.rowIdx,t),i=Math.max(n.lastSelectedCell.rowIdx,t),r=Math.min(n.lastSelectedCell.colIdx,o),d=Math.max(n.lastSelectedCell.colIdx,o);for(let c=s;c<=i;c++)for(let m=r;m<=d;m++){let g=T(n.gridData[c],c),f=P(n.gridData[c],m);n.selectedCells.push({rowIdx:c,colIdx:m,rowId:g,value:f})}}else n.selectedRowIds.clear(),n.selectedCells=[{rowIdx:t,colIdx:o,rowId:l,value:a}],n.lastSelectedCell={rowIdx:t,colIdx:o},n.selectedColumns.clear();M(),R(),O()}function at(e,t,o,l){if(n.cellEditBehavior==="vscode"){let a=n.tableColumns[o];if(!a)return;let s=n.gridData[t];if(!s)return;let i=P(s,o);n.cellPreviewInfo={rowIdx:t,colIdx:o,rowId:l,columnName:a.name,originalValue:i},be()}else n.cellEditBehavior==="modal"?q(t,o,l):ze(t,o,l)}function st(){document.getElementById("filterInput")?.addEventListener("keyup",qe),document.getElementById("pageSizeSelect")?.addEventListener("change",He),document.getElementById("dateFormatSelect")?.addEventListener("change",Ge),document.getElementById("btnFirst")?.addEventListener("click",()=>Z(0)),document.getElementById("btnPrev")?.addEventListener("click",()=>Z(n.currentPageIndex-1)),document.getElementById("btnNext")?.addEventListener("click",()=>Z(n.currentPageIndex+1)),document.getElementById("btnLast")?.addEventListener("click",()=>Z(n.totalPageCount-1))}function it(){let e=document.getElementById("gridContainer");e&&(e.addEventListener("mousedown",_t),e.addEventListener("keydown",Kt),e.addEventListener("click",qt),e.addEventListener("dblclick",Jt),e.addEventListener("mouseover",Xt),e.addEventListener("scroll",Yt,{passive:!0}))}function _t(e){if(e.target.classList.contains("resize-handle")){e.stopPropagation();let t=e.target.closest(".header-cell");t&&t.dataset.column&&et(e,t.dataset.column)}}function Kt(e){if(e.target.classList.contains("column-filter")){let t=e.target.dataset.column;t&&Xe(e,t)}}function qt(e){let t=e.target;if(t.closest(".grid-header")){Ht(e,t);return}Gt(e,t)}function Ht(e,t){if(t.closest(".filter-apply-btn")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Ie(l.dataset.column);return}if(t.closest(".header-bottom")||t.closest(".column-filter")){e.stopPropagation();return}if(t.closest(".select-column-icon")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Ye(e,l.dataset.column);return}if(t.closest(".pin-icon")){e.stopPropagation();let l=t.closest(".header-cell");l&&l.dataset.column&&Ze(e,l.dataset.column);return}if(t.closest(".row-number-header")){ie(e);return}let o=t.closest(".header-top");if(o){let l=o.closest(".header-cell");l&&l.dataset.column&&Je(l.dataset.column);return}}function Gt(e,t){if(t.closest(".pin-icon")){let l=t.closest(".data-row");if(l){let a=l.dataset.rowid,s=Q(a);Qe(e,s)}return}if(t.closest(".expand-icon")){let l=t.closest(".data-cell");if(l){let a=parseInt(l.dataset.rowidx,10),s=parseInt(l.dataset.colidx,10),i=Q(l.closest(".data-row").dataset.rowid);q(a,s,i)}return}if(t.closest(".row-number")){let l=t.closest(".data-row");if(l){let a=Q(l.dataset.rowid),s=parseInt(l.dataset.rowidx,10);ot(e,a,s)}return}let o=t.closest(".data-cell");if(o){let l=parseInt(o.dataset.rowidx,10),a=parseInt(o.dataset.colidx,10),s=o.closest(".data-row"),i=Q(s.dataset.rowid);lt(e,l,a,i);return}}function Jt(e){let t=e.target.closest(".data-cell");if(t&&!t.classList.contains("row-number")){let o=parseInt(t.dataset.rowidx,10),l=parseInt(t.dataset.colidx,10),a=t.closest(".data-row"),s=Q(a.dataset.rowid);at(e,o,l,s)}}function Xt(e){let t=e.target.closest(".data-cell");if(t&&!t.classList.contains("checked-overflow")){let o=t.querySelector(".cell-text");if(o){let l=o.scrollWidth>o.clientWidth;t.classList.toggle("has-overflow",l),t.classList.add("checked-overflow")}}}function Yt(e){let t=e.currentTarget;n.scrollPosition.left=t.scrollLeft,n.scrollPosition.top=t.scrollTop,$()}function Q(e){if(e==null)return e;let t=Number(e);return!isNaN(t)&&e.trim()!==""?t:e}function rt(){document.addEventListener("click",e=>{let t=e.target,o=t.closest(".modal-close, .modal-cancel");if(o){let l=o.dataset.modal;l&&U(l)}t.classList.contains("modal-overlay")&&t.classList.add("hidden")}),document.addEventListener("keydown",e=>{if(e.key==="Escape"){let t=document.querySelector(".modal-overlay:not(.hidden)");t&&(t.classList.add("hidden"),e.preventDefault(),e.stopPropagation(),e.stopImmediatePropagation())}})}function j(e){let t=document.getElementById(e);if(t){t.classList.remove("hidden");let o=t.querySelector("input, select, textarea, button");o&&o.focus()}}function U(e){let t=document.getElementById(e);t&&t.classList.add("hidden")}function ct(){document.getElementById("btnAddRow")?.addEventListener("click",Zt),document.getElementById("btnDeleteRows")?.addEventListener("click",en),document.getElementById("btnAddColumn")?.addEventListener("click",an),document.getElementById("btnSubmitAddRow")?.addEventListener("click",Qt),document.getElementById("btnSubmitDelete")?.addEventListener("click",re),document.getElementById("btnSubmitCreateTable")?.addEventListener("click",ln),document.getElementById("btnAddColumnDef")?.addEventListener("click",()=>mt()),document.getElementById("columnDefinitions")?.addEventListener("click",e=>{let t=e.target.closest(".btn-remove-col");if(t){let o=t.dataset.colid;on(o)}}),document.getElementById("btnSubmitAddColumn")?.addEventListener("click",sn)}function Zt(){if(!n.selectedTable||n.selectedTableType!=="table")return;let e=document.getElementById("addRowForm");e.replaceChildren(),n.tableColumns.forEach(t=>{let o=t.notnull===1&&!t.isPrimaryKey,l=document.createElement("div");l.className="form-field";let a=document.createElement("label");if(a.textContent=t.name,o){let r=document.createElement("span");r.style.color="var(--error-color)",r.textContent="*",a.appendChild(document.createTextNode(" ")),a.appendChild(r)}let s=document.createElement("span");s.style.opacity="0.5",s.textContent=` (${t.type})`,a.appendChild(document.createTextNode(" ")),a.appendChild(s);let i=document.createElement("input");i.type="text",i.dataset.column=t.name,i.dataset.required=o.toString(),t.isPrimaryKey?(i.placeholder="Auto (Primary Key)",i.disabled=!0):o?i.placeholder="Required":i.placeholder="NULL",l.appendChild(a),l.appendChild(i),e.appendChild(l)}),j("addRowModal")}async function Qt(){let e=document.querySelectorAll("#addRowForm input[data-column]:not([disabled])"),t=[];for(let l of e){let a=l.dataset.column,s=l.value.trim();l.dataset.required==="true"&&(s===""||s.toLowerCase()==="null")?(t.push(a),l.style.borderColor="var(--error-color)"):l.style.borderColor=""}if(t.length>0){u(`Required fields missing: ${t.join(", ")}`);return}let o={};for(let l of e){let a=l.dataset.column,s=l.value.trim();s!==""&&(s.toLowerCase()==="null"?o[a]=null:!isNaN(Number(s))&&s!==""?o[a]=Number(s):o[a]=s)}try{u("Inserting row..."),await y.insertRow(n.selectedTable,o),U("addRowModal"),await v(),u("Row inserted - Ctrl+S to save")}catch(l){console.error("Insert failed:",l),u(`Error: ${l.message}`)}}function en(){if(n.selectedColumns.size>0){let e=Array.from(n.selectedColumns);document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${e.length} column${e.length>1?"s":""} (${e.join(", ")})? This will permanently remove the column${e.length>1?"s":""} and all their data.`}else if(n.selectedRowIds.size>0)document.getElementById("deleteConfirmText").textContent=`Are you sure you want to delete ${n.selectedRowIds.size} row${n.selectedRowIds.size>1?"s":""}?`;else return;j("deleteModal")}async function re(){n.selectedColumns.size>0?await nn():n.selectedRowIds.size>0&&await tn()}async function tn(){if(n.selectedRowIds.size===0)return;let e=Array.from(n.selectedRowIds);try{u("Deleting rows..."),await y.deleteRows(n.selectedTable,e),U("deleteModal"),n.selectedRowIds.clear(),await v(),R(),u(`Deleted ${e.length} row${e.length>1?"s":""} - Ctrl+S to save`)}catch(t){console.error("Delete rows failed:",t),u(`Error: ${t.message}`)}}async function nn(){if(n.selectedColumns.size===0)return;let e=Array.from(n.selectedColumns);try{u("Deleting columns...");let t=await y.deleteColumns(n.selectedTable,e);if(t&&t.cancelled){u("Delete cancelled"),U("deleteModal");return}U("deleteModal"),n.selectedColumns.clear(),n.selectedCells=[],n.lastSelectedCell=null,await V(),await K(),await v(),R(),u(`Deleted ${e.length} column${e.length>1?"s":""} - Ctrl+S to save`)}catch(t){console.error("Delete columns failed:",t),u(`Error: ${t.message}`)}}var dt=0;function ut(){document.getElementById("newTableName").value="",document.getElementById("columnDefinitions").replaceChildren(),dt=0,mt(!0),j("createTableModal")}function mt(e=!1){let t=document.getElementById("columnDefinitions"),o=++dt,l=document.createElement("div");l.className="column-def-row",l.id=`colDef_${o}`,Object.assign(l.style,{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center"});let a=document.createElement("input");a.type="text",a.placeholder="Column name",a.className="col-name",a.style.flex="2",e&&(a.value="id"),l.appendChild(a);let s=document.createElement("select");s.className="col-type",s.style.flex="1",["INTEGER","TEXT","REAL","BLOB","NUMERIC"].forEach(f=>{let p=document.createElement("option");p.value=f,p.textContent=f,e&&f==="INTEGER"&&(p.selected=!0),!e&&f==="TEXT"&&(p.selected=!0),s.appendChild(p)}),l.appendChild(s);let i=document.createElement("label");Object.assign(i.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let r=document.createElement("input");r.type="checkbox",r.className="col-pk",r.style.margin="0",e&&(r.checked=!0),i.appendChild(r),i.appendChild(document.createTextNode(" PK")),l.appendChild(i);let d=document.createElement("label");Object.assign(d.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"});let c=document.createElement("input");c.type="checkbox",c.className="col-nn",c.style.margin="0",d.appendChild(c),d.appendChild(document.createTextNode(" NN")),l.appendChild(d);let m=document.createElement("button");m.className="icon-button btn-remove-col",m.dataset.colid=o.toString(),m.title="Remove",e&&(m.disabled=!0);let g=document.createElement("span");g.className="codicon codicon-close",m.appendChild(g),l.appendChild(m),t.appendChild(l)}function on(e){let t=document.getElementById(`colDef_${e}`);t&&t.remove()}async function ln(){let e=document.getElementById("newTableName").value.trim();if(!e){u("Error: Table name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid table name");return}let t=[],o=document.querySelectorAll(".column-def-row");for(let l of o){let a=l.querySelector(".col-name").value.trim(),s=l.querySelector(".col-type").value,i=l.querySelector(".col-pk").checked,r=l.querySelector(".col-nn").checked;a&&t.push({name:a,type:s,primaryKey:i,notNull:r})}if(t.length===0){u("Error: At least one column is required");return}try{u("Creating table..."),await y.createTable(e,t),U("createTableModal"),await V(),u(`Table "${e}" created - Ctrl+S to save`)}catch(l){console.error("Create table failed:",l),u(`Error: ${l.message}`)}}function an(){!n.selectedTable||n.selectedTableType!=="table"||(document.getElementById("newColumnName").value="",document.getElementById("newColumnType").value="TEXT",document.getElementById("newColumnDefault").value="",j("addColumnModal"))}async function sn(){let e=document.getElementById("newColumnName").value.trim(),t=document.getElementById("newColumnType").value,o=document.getElementById("newColumnDefault").value.trim();if(!e){u("Error: Column name is required");return}if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(e)){u("Error: Invalid column name");return}try{u("Adding column..."),await y.addColumn(n.selectedTable,e,t,o),U("addColumnModal"),await K(),await v(),u(`Column "${e}" added - Ctrl+S to save`)}catch(l){console.error("Add column failed:",l),u(`Error: ${l.message}`)}}function pt(){let e=document.getElementById("pragmaSettingsContainer");e&&e.addEventListener("change",t=>{let o=t.target;if(o.matches(".setting-extension")){let l=o.dataset.key,a=o.type==="checkbox"?o.checked:o.value;cn(l,a)}else if(o.matches(".setting-pragma")){let l=o.dataset.name,a=o.dataset.type,s=o.value;a==="number"?s=Number(s):a==="bool"&&(s=s==="true"?1:0),dn(l,s)}})}async function ft(){let e=document.getElementById("settingsModal");e&&(e.classList.remove("hidden"),await ve())}async function ve(){let e=document.getElementById("pragmaSettingsContainer");e.textContent="Loading settings...";try{let[t,o]=await Promise.all([y.getPragmas(),y.getExtensionSettings()]);rn(t,o)}catch(t){console.error("Failed to load settings:",t),e.textContent=`Error loading settings: ${t.message}`,e.style.color="var(--error-color)"}}function rn(e,t){let o=document.getElementById("pragmaSettingsContainer");if(!o)return;let l=(x,C)=>x.map(k=>{let L=String(k),D=String(C).toUpperCase()===L.toUpperCase(),N=document.createElement("option");return N.value=L,N.selected=D,N.textContent=L,N});o.replaceChildren();let a=x=>{let C=document.createElement("div");C.className="setting-section-title",Object.assign(C.style,{fontWeight:"600",marginBottom:"8px",paddingBottom:"4px",borderBottom:"1px solid var(--border-color)"}),C.textContent=x,o.appendChild(C)},s=(x,C,k)=>{let L=document.createElement("div");L.className="form-field";let w=document.createElement("label");if(C.type==="checkbox"?(Object.assign(w.style,{display:"flex",alignItems:"center",gap:"4px",cursor:"pointer"}),C.style.margin="0",w.appendChild(C),w.appendChild(document.createTextNode(x)),L.appendChild(w)):(w.textContent=x,L.appendChild(w),L.appendChild(C)),k){let D=document.createElement("div");D.className="setting-desc",D.textContent=k,L.appendChild(D)}o.appendChild(L)};if(o.children.length>0){let x=document.createElement("div");x.style.height="16px",o.appendChild(x)}a("Extension Settings");let i=document.createElement("input");i.type="checkbox",i.className="setting-extension",i.dataset.key="autoCommit",i.checked=!!t.autoCommit,s("Auto-Commit Changes",i,"Automatically save changes to disk immediately. If disabled, you must save manually (Ctrl+S).");let r=document.createElement("select");r.className="setting-extension",r.dataset.key="doubleClickBehavior",l(["inline","modal","vscode"],t.cellEditBehavior).forEach(x=>r.appendChild(x)),s("Double Click Behavior",r,"Action when double-clicking a cell");let d=document.createElement("div");d.style.height="16px",o.appendChild(d),a("SQLite Settings (Pragmas)");let c=document.createElement("select");c.className="setting-pragma",c.dataset.name="journal_mode",l(["DELETE","TRUNCATE","PERSIST","MEMORY","WAL","OFF"],e.journal_mode).forEach(x=>c.appendChild(x)),s("Journal Mode",c,"Database journaling mode (WAL is recommended for concurrency)");let m=document.createElement("select");m.className="setting-pragma",m.dataset.name="foreign_keys",m.dataset.type="bool";let g=document.createElement("option");g.value="true",g.textContent="ON";let f=document.createElement("option");f.value="false",f.textContent="OFF",Number(e.foreign_keys)===1?g.selected=!0:f.selected=!0,m.appendChild(g),m.appendChild(f),s("Foreign Keys",m,"Enforce foreign key constraints");let p=document.createElement("select");p.className="setting-pragma",p.dataset.name="synchronous",p.dataset.type="number",[{v:0,t:"OFF (0)"},{v:1,t:"NORMAL (1)"},{v:2,t:"FULL (2)"},{v:3,t:"EXTRA (3)"}].forEach(x=>{let C=document.createElement("option");C.value=x.v,C.textContent=x.t,Number(e.synchronous)===x.v&&(C.selected=!0),p.appendChild(C)}),s("Synchronous",p,"Disk synchronization safety level");let h=document.createElement("select");h.className="setting-pragma",h.dataset.name="locking_mode",l(["NORMAL","EXCLUSIVE"],e.locking_mode).forEach(x=>h.appendChild(x)),s("Locking Mode",h,"");let b=document.createElement("select");b.className="setting-pragma",b.dataset.name="auto_vacuum",b.dataset.type="number",[{v:0,t:"NONE (0)"},{v:1,t:"FULL (1)"},{v:2,t:"INCREMENTAL (2)"}].forEach(x=>{let C=document.createElement("option");C.value=x.v,C.textContent=x.t,Number(e.auto_vacuum)===x.v&&(C.selected=!0),b.appendChild(C)}),s("Auto Vacuum",b,"");let I=document.createElement("input");I.type="number",I.className="setting-pragma",I.dataset.name="cache_size",I.dataset.type="number",I.value=e.cache_size,s("Cache Size",I,"Number of pages (positive) or kilobytes (negative)")}async function cn(e,t){try{await y.updateExtensionSetting(e,t),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await ve()}}async function dn(e,t){try{u(`Updating ${e}...`),await y.setPragma(e,t),u(`Updated ${e}`)}catch(o){console.error(`Failed to set ${e}:`,o),u(`Error: ${o.message}`),await ve()}}function ht(e,t){let o=new Map;for(let l of e){let a=t&&t[l.colIdx];a&&(o.has(l.colIdx)||o.set(l.colIdx,{name:a.name,type:a.type,values:new Set}),o.get(l.colIdx).values.add(l.value))}return o}function gt(e){let t=Array.from(e||[]);if(t.length===0)return"";if(t.length>1)return"(mixed values)";let o=t[0];return o===null?"NULL":o instanceof Uint8Array?"[BLOB]":String(o)}function yt(e,t,o){let l=[];for(let a of e){let s=t.get(a.colIdx);if(!s)continue;let i=s.dataset||{},r=i.isnull==="true",d=i.ispatch==="true",c=s.value;if(c===""&&!r)continue;let m=o&&o[a.colIdx];if(!m)continue;let g=c,f="set";if(r)g=null;else if(d)f="json_patch";else{let p=(m.type||"").toUpperCase();(p==="INTEGER"||p==="REAL"||p==="NUMERIC")&&!isNaN(Number(c))&&c.trim()!==""&&(g=Number(c))}l.push({rowId:a.rowId,column:m.name,value:g,originalValue:a.value,operation:f,rowIdx:a.rowIdx,colIdx:a.colIdx})}return l}function xt(){let e=document.getElementById("sidebarPanel");if(!e)return;let t=document.getElementById("sidebarFilterInput");t&&t.addEventListener("input",()=>{n.sidebarFilter=t.value,Be()}),e.addEventListener("click",o=>{let l=o.target;if(l.closest("#btnOpenSettings")){ft();return}if(l.closest("#btnOpenCreateTable")){o.stopPropagation(),ut();return}if(l.closest("#btnReload")){yn();return}if(l.closest("#btnApplyBatchUpdate")){mn();return}let a=l.closest(".list-item");if(a){let d=a.dataset.name,c=a.dataset.type;if(d&&c){gn(d,c);return}}let s=l.closest(".section-title");if(s){if(l.closest(".icon-button")||s.id==="btnOpenSettings")return;let d=s.dataset.section;d&&hn(d)}let i=l.closest(".btn-batch-null");if(i){let d=i.closest(".batch-field");if(d){let c=parseInt(d.dataset.colidx,10);pn(c)}return}let r=l.closest(".btn-batch-patch");if(r){let d=r.closest(".batch-field");if(d){let c=parseInt(d.dataset.colidx,10);fn(c,r)}return}})}async function V(){if(n.isDbConnected)try{let e=await y.fetchSchema();n.schemaCache.tables=(e.tables||[]).map(t=>({name:t.identifier})),n.schemaCache.views=(e.views||[]).map(t=>({name:t.identifier})),n.schemaCache.indexes=(e.indexes||[]).map(t=>({name:t.identifier,table:t.parentTable})),Be()}catch(e){console.error("Error loading schema:",e),u("Error loading schema")}}function Se(e,t){return t?e.filter(o=>o.name.toLowerCase().includes(t)):e}function Te(e,t,o,l){let a=document.getElementById(e);a&&(a.textContent=l?`${t}/${o}`:o)}function Ct(e,t,o,l,a){let s=document.getElementById(e);if(!s)return;if(s.replaceChildren(),t.length===0){let r=document.createElement("li");r.className="list-item",r.style.opacity="0.5",r.textContent=a,s.appendChild(r);return}let i=document.createDocumentFragment();t.forEach(r=>{let d=document.createElement("li");d.className="list-item",n.selectedTable===r.name&&n.selectedTableType===o&&d.classList.add("selected"),d.dataset.name=r.name,o&&(d.dataset.type=o),d.title=r.name;let c=document.createElement("span");c.className=`item-icon codicon ${l}`,d.appendChild(c);let m=document.createElement("span");m.className="item-name",m.textContent=r.name,d.appendChild(m),i.appendChild(d)}),s.appendChild(i)}function un(e,t,o){let l=document.getElementById(e);if(!l)return;if(l.replaceChildren(),t.length===0){let s=document.createElement("li");s.className="list-item",s.style.opacity="0.5",s.textContent=o,l.appendChild(s);return}let a=document.createDocumentFragment();t.forEach(s=>{let i=document.createElement("li");i.className="list-item",i.title=`${s.name} on ${s.table}`;let r=document.createElement("span");r.className="item-icon codicon codicon-list-selection",i.appendChild(r);let d=document.createElement("div");d.className="item-content";let c=document.createElement("span");c.className="item-name",c.textContent=s.name,d.appendChild(c);let m=document.createElement("span");m.className="item-detail",m.textContent=s.table,d.appendChild(m),i.appendChild(d),a.appendChild(i)}),l.appendChild(a)}function Be(){let e=n.sidebarFilter.toLowerCase(),t=e.length>0,o=Se(n.schemaCache.tables,e),l=Se(n.schemaCache.views,e),a=Se(n.schemaCache.indexes,e);Te("tablesBadge",o.length,n.schemaCache.tables.length,t),Te("viewsBadge",l.length,n.schemaCache.views.length,t),Te("indexesBadge",a.length,n.schemaCache.indexes.length,t),Ct("tablesList",o,"table","codicon-table",e?"No matching tables":"No tables"),Ct("viewsList",l,"view","codicon-eye",e?"No matching views":"No views"),un("indexesList",a,e?"No matching indexes":"No indexes")}function O(){let e=document.getElementById("batchUpdateSectionTitle"),t=document.getElementById("batchUpdateList"),o=document.getElementById("batchUpdateCount"),l=document.getElementById("batchUpdateFields");if(!e||!t||!o||!l)return;let a=n.selectedCells.length;if(a===0){e.classList.add("hidden"),t.classList.add("hidden");return}e.classList.remove("hidden"),t.classList.remove("hidden"),e.classList.remove("collapsed"),o.textContent=a;let s=ht(n.selectedCells,n.tableColumns);l.replaceChildren();for(let[i,r]of s){let d=gt(r.values),c=document.createElement("div");c.className="form-field batch-field",c.dataset.colidx=i,c.style.marginBottom="8px";let m=document.createElement("label");m.style.fontSize="11px",m.style.color="var(--text-secondary)";let g=document.createTextNode(r.name+" ");m.appendChild(g);let f=document.createElement("span");f.style.opacity="0.7",f.textContent=r.type||"",m.appendChild(f),c.appendChild(m);let p=document.createElement("div");p.style.display="flex",p.style.gap="4px";let h=document.createElement("input");h.type="text",h.className="batch-input",h.placeholder=d,h.dataset.colidx=i,h.style.flex="1",h.style.minWidth="0",p.appendChild(h);let b=document.createElement("button");b.className="btn-secondary btn-batch-null",b.style.padding="2px 6px",b.title="Set to NULL",b.textContent="NULL",p.appendChild(b);let I=document.createElement("button");I.className="btn-secondary btn-batch-patch",I.style.padding="2px 6px",I.title="JSON Patch",I.textContent="{}",p.appendChild(I),c.appendChild(p),l.appendChild(c)}}async function mn(){if(n.selectedCells.length===0)return;let e=document.querySelectorAll(".batch-input"),t=new Map;for(let l of e){let a=parseInt(l.dataset.colidx,10);if(t.set(a,l),l.dataset.ispatch==="true")try{JSON.parse(l.value)}catch{let i=n.tableColumns[a];u(`Invalid JSON for patch in ${i?.name??`column ${a}`}`);return}}let o=yt(n.selectedCells,t,n.tableColumns);if(o.length===0){u("No values entered for batch update");return}try{u(`Updating ${o.length} cells...`);let l=`Batch update ${o.length} cells`,a=o.map(r=>({rowId:r.rowId,column:r.column,value:r.value,originalValue:r.originalValue,operation:r.operation}));if(await y.updateCellBatch(n.selectedTable,a,l),!o.some(r=>r.operation==="json_patch"))for(let r of o)n.gridData[r.rowIdx][r.colIdx+B()]=r.value;await v(!1);let i=[];for(let r of n.selectedCells){let d=n.gridData[r.rowIdx][r.colIdx+B()];i.push({...r,value:d})}n.selectedCells=i,O(),u("Batch update completed")}catch(l){console.error("Batch update failed:",l),u(`Batch update failed: ${l.message}`)}}function pn(e){let t=document.querySelector(`.batch-input[data-colidx="${e}"]`),o=document.querySelector(`.batch-field[data-colidx="${e}"] .btn-batch-patch`);t&&(t.value="",t.placeholder="SET TO NULL",t.dataset.isnull="true",t.dataset.ispatch="false",t.style.fontStyle="italic",o&&(o.style.background="",o.style.color=""))}function fn(e,t){let o=document.querySelector(`.batch-input[data-colidx="${e}"]`);o&&(o.dataset.ispatch==="true"?(o.dataset.ispatch="false",o.placeholder="(mixed values)",t.style.background="",t.style.color=""):(o.dataset.ispatch="true",o.dataset.isnull="false",o.placeholder='JSON Patch (e.g. {"a": 1})',o.style.fontStyle="normal",t.style.background="var(--accent-color)",t.style.color="white"))}function hn(e){let t=document.getElementById(`${e}List`),o=document.querySelector(`.section-title[data-section="${e}"]`);t&&o&&(t.classList.toggle("hidden"),o.classList.toggle("collapsed"))}async function gn(e,t){n.selectedTable=e,n.selectedTableType=t,n.currentPageIndex=0,n.sortedColumn=null,n.sortAscending=!0,n.filterQuery="",n.columnFilters={},n.selectedRowIds.clear(),n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),n.pinnedColumns.clear(),n.pinnedRowIds.clear(),n.columnWidths={},n.scrollPosition={top:0,left:0},Be();let o=document.getElementById("tableNameLabel");o&&(o.textContent=e);let l=document.getElementById("filterInput");l&&(l.value=""),await K(),await v(!0,!1),$()}async function yn(){if(n.isDbConnected)try{u("Reloading..."),await y.refreshFile(),await V(),n.selectedTable&&(await K(),await v()),u("Reloaded")}catch(e){console.error("Reload failed:",e),u(`Reload failed: ${e.message}`)}}function wt(){document.getElementById("btnExport")?.addEventListener("click",Cn),document.getElementById("btnSubmitExport")?.addEventListener("click",xn),document.getElementById("exportFormat")?.addEventListener("change",bt)}function Cn(){if(!n.selectedTable)return;let e=document.getElementById("exportFormat");e&&(e.value="csv");let t=document.getElementById("exportColumns");t&&(t.replaceChildren(),n.tableColumns.forEach(o=>{let l=document.createElement("div"),a=document.createElement("label");Object.assign(a.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let s=document.createElement("input");s.type="checkbox",s.className="export-col-check",s.value=o.name,s.checked=!0,s.style.margin="0",a.appendChild(s),a.appendChild(document.createTextNode(o.name)),t.appendChild(a)})),bt(),j("exportModal")}function bt(){let e=document.getElementById("exportFormat").value,t=document.getElementById("exportOptions");if(t.replaceChildren(),e==="csv"||e==="excel"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportHeader",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Headers")),t.appendChild(o)}else if(e==="sql"){let o=document.createElement("label");Object.assign(o.style,{display:"flex",alignItems:"center",gap:"3px",marginBottom:"4px",fontSize:"13px",cursor:"pointer"});let l=document.createElement("input");l.type="checkbox",l.id="exportTableName",l.checked=!0,l.style.margin="0",o.appendChild(l),o.appendChild(document.createTextNode(" Include Table Name")),t.appendChild(o)}}async function xn(){let e=document.getElementById("exportFormat").value,t=document.querySelectorAll(".export-col-check:checked"),o=Array.from(t).map(a=>a.value);if(o.length===0){u("Error: Select at least one column");return}let l={};if(e==="csv"||e==="excel"?l.header=document.getElementById("exportHeader")?.checked??!0:e==="sql"&&(l.includeTableName=document.getElementById("exportTableName")?.checked??!0),n.selectedTableType==="table"){let a=Array.from(n.selectedRowIds);a.length>0&&(l.rowIds=a)}try{u("Exporting..."),U("exportModal"),await y.exportTable({table:n.selectedTable},o,null,null,{format:e,...l}),u("Export initiated")}catch(a){console.error("Export failed:",a),u(`Export failed: ${a.message}`)}}async function Et(){if(n.selectedCells.length!==0)try{let e;if(n.selectedCells.length===1){let t=n.selectedCells[0].value;t==null?e="":t instanceof Uint8Array?e="[BLOB]":e=String(t)}else{let t=[...new Set(n.selectedCells.map(s=>s.rowIdx))].sort((s,i)=>s-i),o=[...new Set(n.selectedCells.map(s=>s.colIdx))].sort((s,i)=>s-i),l=new Map;for(let s of n.selectedCells)l.set(`${s.rowIdx},${s.colIdx}`,s.value);let a=[];for(let s of t){let i=[];for(let r of o){let d=`${s},${r}`,c=l.has(d)?l.get(d):"";c==null?c="":c instanceof Uint8Array?c="[BLOB]":(c=String(c),c=c.replace(/\t/g," ").replace(/\n/g," ")),i.push(c)}a.push(i.join(" "))}e=a.join(` `)}await navigator.clipboard.writeText(e),u(`Copied ${n.selectedCells.length} cell${n.selectedCells.length>1?"s":""}`)}catch(e){console.error("Copy failed:",e),u("Copy failed: "+e.message)}}async function It(){if(n.selectedRowIds.size!==0)try{let e=[];for(let l=0;ld==null?"":d instanceof Uint8Array?"[BLOB]":String(d));e.push(r.join(" "))}}let o=[n.tableColumns.map(l=>l.name).join(" "),...e].join(` `);await navigator.clipboard.writeText(o),u(`Copied ${e.length} row${e.length>1?"s":""} to clipboard`)}catch(e){console.error("Copy failed:",e),u("Copy failed: "+e.message)}}async function vt(){if(n.selectedCells.length!==0){if(n.selectedTableType!=="table"){u("Views are read-only");return}try{u("Clearing cells...");let e=[];for(let o of n.selectedCells){let l=n.tableColumns[o.colIdx];if(!l)continue;let s=l.notnull===1?"":null;e.push({rowId:o.rowId,column:l.name,value:s,originalValue:o.value,rowIdx:o.rowIdx,colIdx:o.colIdx})}let t=`Clear ${e.length} cell${e.length>1?"s":""}`;await y.updateCellBatch(n.selectedTable,e,t);for(let o of e)n.gridData[o.rowIdx][o.colIdx+B()]=o.value;n.selectedCells=[],n.lastSelectedCell=null,n.selectedColumns.clear(),await v(),R(),u(`${t} - Ctrl+S to save`)}catch(e){console.error("Clear cells failed:",e),u(`Clear failed: ${e.message}`)}}}var ce=50*1024*1024,Le=!1;function St(){let e=document.getElementById("gridContainer");if(!e){console.error("gridContainer not found");return}document.addEventListener("dragover",t=>t.preventDefault()),document.addEventListener("drop",t=>t.preventDefault()),e.addEventListener("dragover",wn),e.addEventListener("dragleave",bn),e.addEventListener("drop",En)}var F=null;function wn(e){e.preventDefault(),e.dataTransfer.dropEffect="copy";let t=e.target.closest(".data-cell");t&&!t.classList.contains("row-number")?(F&&F!==t&&F.classList.remove("drag-over"),t.classList.add("drag-over"),F=t):F&&(F.classList.remove("drag-over"),F=null)}function bn(e){e.target}async function En(e){e.preventDefault(),F&&(F.classList.remove("drag-over"),F=null);let t=e.target.closest(".data-cell");if(!t||t.classList.contains("row-number"))return;if(e.dataTransfer.files.length>0){let l=e.dataTransfer.files[0];await In(t,l.name,l);return}let o=e.dataTransfer.getData("text/uri-list");if(o){let l=o.split(/\r?\n/);if(l.length>0&&l[0]){let a=l[0],s="unknown_file";try{let i=a.split("/");s=decodeURIComponent(i[i.length-1])}catch(i){console.warn("Failed to parse name from URI",i)}await vn(t,s,a);return}}}async function In(e,t,o){if(o.size>ce){let l=(o.size/1048576).toFixed(1),a=(ce/(1024*1024)).toFixed(0);u(`File too large (${l}MB). Maximum is ${a}MB.`);return}try{u(`Reading ${t}...`);let l=await Sn(o),a=new Uint8Array(l);await Tt(e,t,a)}catch(l){console.error("File read failed:",l),u(`File read failed: ${l.message}`)}}async function vn(e,t,o){try{u(`Fetching ${t}...`);let l=await y.readWorkspaceFileUri(o),a;if(l instanceof Uint8Array)a=l;else if(l&&l.type==="Buffer"&&Array.isArray(l.data))a=new Uint8Array(l.data);else if(l&&typeof l=="object"&&Object.keys(l).some(s=>!isNaN(s)))a=new Uint8Array(Object.values(l));else throw console.error("Unknown data format from backend:",l),new Error("Received invalid data format from backend");await Tt(e,t,a)}catch(l){console.error("URI upload failed:",l),u(`Upload failed: ${l.message}`)}}async function Tt(e,t,o){if(Le){u("Upload already in progress...");return}if(o.byteLength>ce){let d=(o.byteLength/1048576).toFixed(1),c=(ce/(1024*1024)).toFixed(0);u(`File too large (${d}MB). Maximum is ${c}MB.`);return}let l=parseInt(e.dataset.rowidx,10),a=parseInt(e.dataset.colidx,10);if(!n.gridData)return;let s=n.gridData[l];if(!s)return;let i=T(s,l),r=n.tableColumns[a];if(n.selectedTableType!=="table"){u("Cannot upload to a view");return}Le=!0,n.isLoadingData=!0;try{u(`Uploading ${t} (${Tn(o.byteLength)})...`);let d=s[a+B()];await y.updateCell(n.selectedTable,i,r.name,o,d),n.gridData[l][a+B()]=o,Bn(e,o),u(`Uploaded ${t}`)}catch(d){console.error("Upload failed:",d);let c=d.message||String(d);c.includes("timeout")&&(c="Upload timed out. Try a smaller file."),u(`Upload failed: ${c}`)}finally{Le=!1,n.isLoadingData=!1}}function Sn(e){return new Promise((t,o)=>{let l=new FileReader;l.onload=()=>t(l.result),l.onerror=()=>o(l.error),l.readAsArrayBuffer(e)})}function Tn(e){if(e===0)return"0 B";let t=1024,o=["B","KB","MB","GB"],l=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,l)).toFixed(2))+" "+o[l]}function Bn(e,t){let o=_(t);e.textContent="";let l=document.createElement("span");l.className="cell-text",l.textContent=o,e.appendChild(l);let a=document.createElement("span");a.className="expand-icon codicon codicon-link-external",a.title="View full content",e.appendChild(a),e.classList.remove("null-value")}var Bt={async refreshContent(e){return n.isDbConnected&&(await V(),!(n.schemaCache.tables.some(o=>o.name===n.selectedTable)||n.schemaCache.views.some(o=>o.name===n.selectedTable))&&n.selectedTable?(n.selectedTable=null,n.selectedTableType=null,document.getElementById("tableNameLabel").textContent="No table selected",xe()):n.selectedTable&&await v(!1)),{success:!0}},async updateColorScheme(e){return document.documentElement.style.colorScheme=e,{success:!0}},async updateCellEditBehavior(e){return n.cellEditBehavior=e,{success:!0}}};function Ln(){window.addEventListener("message",e=>{let t=e.data;if(t&&t.kind==="invoke"){let{correlationId:l,methodName:a,parameters:s}=t,i=Bt[a];typeof i=="function"?Promise.resolve(i.apply(Bt,s||[])).then(r=>{Ae(l,r)}).catch(r=>{ye(l,r instanceof Error?r.message:String(r))}):ye(l,`Unknown method: ${a}`);return}if(!t||t.channel!=="rpc")return;let o=t.content;o&&o.kind==="response"&&ke(o)})}Ln();async function Rn(){try{xt(),ct(),wt(),rt(),pt(),Oe(),st(),it(),Me(),St();let e=document.getElementById("openInVsCodeBtn");e&&(e.style.display="none"),u("Connecting to database...");let t=await y.initialize();n.isDbConnected=!0,await y.ping(),await V(),u("Ready"),xe(),document.addEventListener("keydown",async o=>{if(o.key==="Escape"&&!n.editingCellInfo&&!document.querySelector(".modal-overlay:not(.hidden)")&&oe(),(o.metaKey||o.ctrlKey)&&o.key==="c"){if(n.editingCellInfo||document.activeElement.tagName==="INPUT")return;n.selectedCells.length>0?(o.preventDefault(),await Et()):n.selectedRowIds.size>0&&(o.preventDefault(),await It())}if((o.metaKey||o.ctrlKey)&&o.key==="a"){if(n.editingCellInfo||document.activeElement.tagName==="INPUT")return;n.selectedTable&&(o.preventDefault(),ie(o))}if((o.metaKey||o.ctrlKey)&&(o.key==="Delete"||o.key==="Backspace")){if(n.editingCellInfo||document.activeElement.tagName==="INPUT"||document.activeElement.tagName==="TEXTAREA")return;n.selectedTable&&n.selectedTableType==="table"&&(o.preventDefault(),n.selectedColumns.size>0?await re():n.selectedRowIds.size>0?await re():n.selectedCells.length>0&&await vt())}})}catch(e){console.error("Init error:",e),ne(e.message)}}Rn();})();