Skip to content

Create developer testing UI #458

Closed
Closed

Description

@malibio

Create developer testing UI

Parent Epic: #451

Dependencies

Overview

Build developer-focused UI for interactive testing and comparison of LanceDB vs Turso implementations. Enables hands-on exploration, operation execution, and real-time performance visualization.

Self-Contained Scope

  • Simple developer testing interface
  • Execute operations on both backends
  • Display side-by-side results
  • Show performance metrics
  • Run benchmark suites from UI
  • Export test results
  • Zero impact on production UI

Implementation Approach

Phase 1: Basic Testing Interface

  • Create dev-only route or page
  • Backend selector (Turso/LanceDB/Both)
  • Operation selector (CRUD, Query, Structural)
  • Input forms for operation parameters
  • Execute button and results display

Phase 2: Comparison Mode

  • Side-by-side result display
  • Diff view for differences
  • Timing comparison visualization
  • Success/error status indicators
  • Operation history log

Phase 3: Benchmark Integration

  • Run benchmark suite from UI
  • Display benchmark progress
  • Visualize results with charts
  • Export benchmark reports
  • Save results for comparison

Phase 4: Advanced Features

  • Query builder interface
  • Batch operation testing
  • Index management controls
  • Version history viewer (LanceDB)
  • Dataset size selector

Acceptance Criteria

  • Developer testing UI accessible in app
  • All operation types executable from UI
  • Side-by-side comparison mode functional
  • Performance metrics displayed
  • Benchmark suite runnable from UI
  • Results exportable to JSON/CSV
  • UI documented with screenshots
  • Dev-only access (not in production builds)

Technical Specifications

Route/Page Structure:

// src/routes/dev/database-comparison/+page.svelte
<script lang="ts">
  import { invoke } from '@tauri-apps/api/tauri';
  
  let backend = 'both';  // 'turso' | 'lancedb' | 'both'
  let operation = 'create';
  let operationData = {};
  let results = {
    turso: null,
    lancedb: null,
    comparison: null,
  };
  
  async function executeOperation() {
    if (backend === 'both') {
      results.comparison = await invoke('compare_backends', {
        operation,
        data: operationData,
      });
    } else {
      const command = backend === 'turso' 
        ? `${operation}_node`
        : `${operation}_node_lance_experimental`;
      results[backend] = await invoke(command, operationData);
    }
  }
</script>

Operation Forms:

<div class="operation-selector">
  <select bind:value={operation}>
    <option value="create">Create Node</option>
    <option value="read">Read Node</option>
    <option value="update">Update Node</option>
    <option value="delete">Delete Node</option>
    <option value="query">Query Nodes</option>
    <option value="indent">Indent Operation</option>
    <option value="benchmark">Run Benchmarks</option>
  </select>
</div>

{#if operation === 'create'}
  <CreateNodeForm bind:data={operationData} />
{:else if operation === 'query'}
  <QueryBuilderForm bind:data={operationData} />
{:else if operation === 'benchmark'}
  <BenchmarkConfigForm bind:data={operationData} />
{/if}

<button on:click={executeOperation}>Execute</button>

Comparison Results Display:

{#if results.comparison}
  <div class="comparison-results">
    <div class="metrics">
      <div class="metric">
        <span>Turso:</span>
        <span class="time">{results.comparison.turso_time_ms}ms</span>
      </div>
      <div class="metric">
        <span>LanceDB:</span>
        <span class="time">{results.comparison.lance_time_ms}ms</span>
      </div>
      <div class="metric">
        <span>Winner:</span>
        <span class="winner">{results.comparison.winner}</span>
      </div>
    </div>
    
    <div class="results-side-by-side">
      <div class="result-panel">
        <h4>Turso Result</h4>
        <pre>{JSON.stringify(results.comparison.turso_result, null, 2)}</pre>
      </div>
      <div class="result-panel">
        <h4>LanceDB Result</h4>
        <pre>{JSON.stringify(results.comparison.lance_result, null, 2)}</pre>
      </div>
    </div>
    
    {#if !results.comparison.results_match}
      <div class="differences">
        <h4>Differences Detected</h4>
        <ul>
          {#each results.comparison.differences as diff}
            <li>{diff}</li>
          {/each}
        </ul>
      </div>
    {/if}
  </div>
{/if}

Benchmark Visualization:

<script lang="ts">
  import { Chart } from 'chart.js';
  
  async function runBenchmarks() {
    benchmarkRunning = true;
    const report = await invoke('run_performance_benchmarks', {
      datasetSizes: [100, 1000, 10000],
    });
    
    // Visualize results
    createComparisonChart(report.comparisons);
    benchmarkResults = report;
    benchmarkRunning = false;
  }
  
  function createComparisonChart(comparisons) {
    // Create bar chart comparing Turso vs LanceDB
    // for each operation across dataset sizes
  }
</script>

<div class="benchmark-section">
  <button on:click={runBenchmarks} disabled={benchmarkRunning}>
    {benchmarkRunning ? 'Running...' : 'Run Benchmarks'}
  </button>
  
  {#if benchmarkResults}
    <canvas bind:this={chartCanvas}></canvas>
    <button on:click={exportResults}>Export Results</button>
  {/if}
</div>

Query Builder:

<div class="query-builder">
  <div class="filter-builder">
    <label>Node Type:</label>
    <select bind:value={queryFilters.type}>
      <option value="">All</option>
      <option value="task">Task</option>
      <option value="text">Text</option>
      <option value="date">Date</option>
    </select>
  </div>
  
  <div class="json-path-filter">
    <label>JSON Path:</label>
    <input bind:value={queryFilters.jsonPath} 
           placeholder="metadata.status" />
    <label>Value:</label>
    <input bind:value={queryFilters.jsonValue} />
  </div>
  
  <button on:click={buildAndExecuteQuery}>Execute Query</button>
</div>

Dev-Only Route Guard:

// Only accessible in development or with feature flag
export const load = ({ url }) => {
  if (import.meta.env.PROD && !import.meta.env.VITE_ENABLE_DEV_TOOLS) {
    throw redirect(307, '/');
  }
};

Resources & References

UI Frameworks:

  • Svelte components and reactivity
  • Chart.js for visualization
  • Tauri invoke API for backend calls

Related Commands:

Related Issues:

Definition of Done

  • Developer testing UI implemented and accessible
  • All CRUD operations executable from UI
  • Comparison mode shows side-by-side results
  • Performance metrics displayed accurately
  • Benchmark suite integrated and functional
  • Results exportable to multiple formats
  • UI only accessible in dev mode or with feature flag
  • Documentation includes usage guide and screenshots

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

Activity

  1. malibio commented on Jan 26, 2026

    @malibio
    CollaboratorAuthor

    Closing as superseded. This was part of the LanceDB evaluation (Epic #451). NodeSpace has committed to SurrealDB as the persistence layer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions