saropa_drift_advisor 0.3.0
saropa_drift_advisor: ^0.3.0 copied to clipboard
Debug-only HTTP server that exposes SQLite/Drift table data as JSON and a minimal web viewer. Use from any Drift (or raw SQLite) app via an injectable query callback.
Changelog #
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
pub.dev — saropa_drift_advisor
0.3.0 Unreleased #
Package renamed from saropa_drift_viewer to saropa_drift_advisor.
Update your pubspec.yaml dependency and replace package:saropa_drift_viewer/
imports with package:saropa_drift_advisor/. All APIs are unchanged.
This release also improves everyday usability with a visual query builder, smarter data formatting, per-table state persistence, and one-click cell copying.
Added #
-
VS Code extension: Isar-to-Drift schema generator — Convert Isar
@collectionclasses to Drift table definitions. Scan the workspace to auto-discover all@collection/@embeddedfiles, or manually pick Dart source files or Isar JSON schema exports. The parser extracts collections, embedded objects, links, indexes, and enum fields. Type mapper converts Isar types to Drift column types, generates foreign key columns forIsarLink, junction tables forIsarLinks, and supports configurable strategies for embedded objects (JSON serialization or column flattening) and enums (ordinal int or name text). Interactive webview panel shows a live preview of the generated Drift code with options to copy, open as editor tab, or save to file. New files:isar-gen/isar-gen-types.ts,isar-gen/isar-parser.ts,isar-gen/isar-json-parser.ts,isar-gen/isar-type-mapper.ts,isar-gen/isar-drift-codegen.ts,isar-gen/isar-gen-panel.ts,isar-gen/isar-gen-html.ts,isar-gen/isar-gen-commands.ts,isar-gen/isar-workspace-scanner.ts. -
VS Code extension: Pre-launch health check tasks — Register VS Code tasks ("Drift: Health Check", "Drift: Anomaly Scan", "Drift: Index Coverage") that can be wired into
launch.jsonaspreLaunchTaskto automatically scan for database issues every time you press F5. Tasks useCustomExecutionwith aPseudoterminalfor formatted terminal output showing connection status, index coverage gaps, and data anomalies with severity icons. Exit code 1 blocks launch when errors are found; warnings pass by default (configurable viadriftViewer.tasks.blockOnWarnings). Adrift-healthproblem matcher routes task output to the Problems panel. New API client methods:indexSuggestions(),anomalies(). New files:tasks/drift-task-provider.ts,tasks/health-check-runner.ts. -
VS Code extension: Peek / Go to Definition for SQL names — Place the cursor on a table or column name inside a raw SQL string in Dart code, then press Alt+F12 (Peek Definition) or F12 (Go to Definition) to jump to the corresponding Drift table class or column getter. Table names are resolved via snake_case-to-PascalCase conversion (e.g.
users→class Users extends Table), and column names match both snake_case and camelCase getters (e.g.created_at→get createdAt). Schema metadata is cached from the API with 30-second TTL and auto-cleared on generation changes. New files:definition/drift-definition-provider.ts,definition/sql-string-detector.ts. -
VS Code extension: CodeLens on Drift table classes — Inline annotations appear above
class ... extends Tabledefinitions in Dart files. Each table class shows a live row count from the running server (e.g. "42 rows"), a "View in Drift Viewer" action that opens the webview panel, and a "Run Query" action that executesSELECT *and opens the results as JSON in a side editor. Row counts update automatically via the generation watcher. When the server is offline, lenses show "not connected". Dart PascalCase class names are mapped to SQL snake_case table names with case-insensitive fallback. New files:codelens/drift-codelens-provider.ts,codelens/table-name-mapper.ts. New commands:driftViewer.viewTableInPanel,driftViewer.runTableQuery. -
VS Code extension: Query Performance Panel in Debug sidebar — Live-updating tree panel appears in the Run & Debug sidebar during active Dart debug sessions when the Drift server is connected. Shows aggregate stats (query count, total/avg duration), slow queries (>500ms with flame icon, >100ms with watch icon), and recent queries in collapsible categories. Click any query to view full SQL with duration, row count, and timestamp in a readonly editor. Auto-refreshes every 3 seconds (configurable via
driftViewer.performance.refreshIntervalMs). Panel visibility controlled by compoundwhenclause (inDebugMode && driftViewer.serverConnected) with server health check on debug session start. Toolbar buttons for manual refresh and clearing stats. Concurrency guard prevents overlapping refresh calls. New files:debug/performance-items.ts,debug/performance-tree-provider.ts. New commands:driftViewer.refreshPerformance,driftViewer.clearPerformance,driftViewer.showQueryDetail. New settings:driftViewer.performance.slowThresholdMs,driftViewer.performance.refreshIntervalMs. -
VS Code extension: Saropa Log Capture integration — Optional bridge to the Saropa Log Capture extension for unified log timeline visibility. When
saropa.saropa-log-captureis installed, registers as an integration provider contributing session-start headers (server URL, slow threshold) and session-end summaries (query stats, top slow queries). Connection lifecycle events are written viawriteLine(). Supports three verbosity modes viadriftViewer.performance.logToCapturesetting:off,slow-only(default), andall. No hard dependency — all methods are no-ops when the extension is absent. New file:debug/log-capture-bridge.ts. -
Web UI: visual query builder — Collapsible "Query builder" section appears below table metadata when viewing any table. Build SQL queries visually with SELECT column checkboxes, type-aware WHERE clause builder (text: contains/equals/starts-with; numeric: comparison operators; blob: null checks only), ORDER BY column/direction picker, and LIMIT control. Live SQL preview updates as selections change. "Run query" executes via
POST /api/sqlwith loading state feedback; "Reset to table view" returns to raw data. Query builder state is persisted per table via localStorage. Column types sourced from existing/api/schema/metadataendpoint — no new server endpoints. -
Web UI: copy cell to clipboard — Hover over any data table cell to reveal a copy button. Click copies the raw cell value via
navigator.clipboard.writeText()with a brief "Copied!" toast notification (auto-dismisses after 1.2s). Works alongside FK navigation links without interference (copy button usesstopPropagation). Copy buttons are preserved during search highlighting. -
Web UI: filter state caching per table — Table view state (row filter text, pagination limit/offset, display format preference, query builder configuration) is automatically saved to localStorage when switching tables and restored when returning. "Clear state" button in the pagination bar resets all cached state for the current table. localStorage key pattern:
drift-viewer-table-state-{tableName}. -
Web UI: data type display toggle — "Display: Raw / Formatted" dropdown in the table toolbar toggles between raw SQLite values and human-readable formatting. Epoch timestamps (seconds or milliseconds after year 2000) in date-named columns display as ISO 8601 strings. Integer 0/1 in boolean-named columns (
is_*,has_*,*_enabled, etc.) display astrue/false. Formatted cells show the raw value below in muted text and in the tooltip, both individually copyable. Preference is saved per table as part of filter state caching.
0.2.4 #
This release adds powerful web UI features for exploring and understanding your data: charts, natural language queries, anomaly detection, collaborative sharing, and a query performance monitor.
Added #
- Collaborative debug sessions — Share the current viewer state (selected table, SQL query, filters, pagination) as a URL. Click the "Share" button in the header, optionally add a note, and the URL is copied to the clipboard. Teammates open the URL to see the exact same view with an info bar and any text annotations. Server stores sessions in memory with 1-hour auto-expiry and a 50-session cap. Three new endpoints:
POST /api/session/share,GET /api/session/{id},POST /api/session/{id}/annotate. Session business logic is extracted into a dedicatedDriftDebugSessionStoreclass (lib/src/drift_debug_session.dart) for clean separation from HTTP handling. Client-side JS is modularized into seven named functions for state capture, clipboard handling, UI restoration, and annotation rendering. - Web UI: SQL bookmarks — Save, name, and organize frequently used SQL queries. Bookmarks persist in
localStorageand appear in a dropdown below the history selector. Save current query with a custom name, delete selected bookmarks, export all as JSON for version control, and import from JSON with automatic deduplication. Purely client-side — no server changes. - Web UI: EXPLAIN QUERY PLAN viewer — "Explain" button next to Run in the SQL runner. Sends
POST /api/sql/explainto visualize SQLite's query execution plan as an indented tree. Full table scans are highlighted red with a warning; index lookups are highlighted green. Read-only SQL validation is enforced before explaining. Server handler reuses shared body-reading/validation helper (_readAndValidateSqlBody) to avoid duplication with the Run SQL handler. Run and Explain buttons disable each other during requests to prevent race conditions. - Web UI: data charts — Bar, pie, line/time-series, and histogram charts rendered as inline SVG from SQL query results. Chart type selector, X/Y axis pickers, and Render button appear after SQL results. Large datasets (>500 rows) are automatically sampled for SVG performance. Pie chart groups slices below 2% into "Other" and handles single-slice (100%) rendering. All chart colors use CSS variables for theme support. Zero new dependencies (pure inline SVG).
- Web UI: natural language to SQL — "Ask in English" input converts plain English questions (e.g. "how many users", "latest 5 orders", "average price") to SQL via pattern matching. New
GET /api/schema/metadataendpoint provides table names, column names/types, primary keys, and row counts. Schema metadata is cached client-side. Supports count, average, sum, min/max, distinct, latest/oldest, and group-by patterns. Converted SQL is editable before running. No external API keys or dependencies. - Web UI: interactive table relationships — Click any foreign key value in the data table to navigate directly to the referenced row in the parent table. New
GET /api/table/{name}/fk-metaendpoint returns FK metadata fromPRAGMA foreign_key_list. FK columns display an arrow icon (↗) in the header and values render as clickable links (→). Navigation breadcrumb trail tracks the path through tables with a Back button. FK metadata is cached per table. Loading indicator shown during first FK fetch. Data renders as an HTML table (replacing JSON<pre>blocks) in all view modes. Zero new dependencies. - Web UI: data anomaly detection — One-click "Scan for anomalies" analyzes all tables for data quality issues: NULL values in nullable columns (with percentage), empty strings in text columns, orphaned foreign key references, duplicate rows, and numeric outliers (max > 10× average). Results display as a severity-coded list (error/warning/info) with colored border indicators. Server-side analysis via
GET /api/analytics/anomaliesusing pure SQL heuristics — no AI/ML dependencies. Table row count is cached per-table to avoid redundant queries. Five modular detection methods keep the handler clean. - Web UI: data import (debug only) — Import CSV, JSON, or SQL files into any table during debug sessions via
POST /api/import. Opt-in: requires passing the newDriftDebugWriteQuerycallback toDriftDebugServer.start(); returns 501 if not configured. Collapsible UI section with table selector, format selector, file picker with preview, and confirmation dialog. Auto-detects format from file extension. Per-row error reporting with partial import support. Import logic extracted into modularDriftDebugImportProcessorclass (lib/src/drift_debug_import.dart) andDriftDebugImportResultvalue class (lib/src/drift_debug_import_result.dart). CSV parser handles quoted fields, escaped quotes, CR+LF line endings, and UTF-8 BOM. Column names are SQL-escaped to prevent injection. Live-refresh triggers immediately after import via generation bump. - Web UI: live query performance monitor — Track execution time of every SQL query passing through the debug server. Collapsible "Query performance" panel with Refresh and Clear buttons.
GET /api/analytics/performancereturns summary stats (total queries, total/avg duration), slow queries (>100ms, top 20 sorted by duration), query patterns (grouped by first 60 chars, top 20 by total time), and recent queries (last 50).DELETE /api/analytics/performanceclears the timing buffer. Query callback is wrapped withStopwatchatstart()so all queries (including internal ones) are timed automatically. 500-entry ring buffer with automatic eviction. Color-coded durations in the UI (red >100ms, orange >50ms). Auto-fetches data on first expand.QueryTimingdata class inserver_types.dart; route constants inserver_constants.dart; JS inhtml_content.dart.
Fixed #
- Mixin corruption — Removed JavaScript
initPerformancecode that was accidentally inserted into theDriftDebugServer.start()Dart parameter list across multiple prior commits, causing analyzer errors.
0.2.3 #
We're focusing on backend tooling and documentation in this release.
Fixed #
- CI workflow: trigger branch changed from
mastertomainto match the repository default branch; PRs and pushes now correctly run CI. - Static analysis: added curly braces to three bare
if-body statements indrift_debug_server_io.dart(lint:always_put_control_body_on_new_line). - Static analysis: wrapped three doc-comment URL paths containing angle brackets in backticks to prevent HTML interpretation (lint:
unintended_html_in_doc_comment). - Dependency lower bounds: bumped
webview_flutterfrom^4.12.0to^4.13.0so the minimum version includesonSslAuthError/SslAuthError(added in 4.13.0), fixing the downgrade analysis failure.
Changed #
- Added a banner image to the README
- Publish tooling:
scripts/publish.pynow checks whether the package already exists on pub.dev before offering a localdart pub publishfor first-time publishes. - CI workflow: removed the one-time "Add uploader" workflow and inline step; maintainers can use
dart pub uploaderor the pub.dev UI directly when needed. - Tooling docs: clarified in
analysis_options.yamlcomments that saropa_lints 6.x does not provideanalysis_options.yamlas an include target. - Upgraded
saropa_lintsfrom 6.2.2 to 8.0.7 (professional tier: 1649 → 1666 rules enabled).
0.2.2 #
0.2.1 #
In this release we only updated the CHANGELOG link to point at the repo until the package was live on pub.dev.
Changed #
- CHANGELOG: link to GitHub until package was on pub.dev.
0.2.0 #
In this release we focused on making the viewer more useful day to day: the table view now refreshes when data changes, you can run read-only SQL from the browser, and you can protect the viewer with a token or Basic auth when using a dev tunnel. We added a schema diagram, CSV export, snapshot/time travel, and a Flutter overlay so you can open the viewer from your app.
Fixed #
-
Lint and validation — DriftDebugServer singleton uses nullable backing field + getter (no
late) for avoid_late_keyword. POST /api/sql checks Content-Type before decoding; body decode/validation in_parseSqlBody(require_content_type_validation, require_api_response_validation). WebView route:buildWebViewRouteusesUri.tryParseand allows only http/https; invalid URLs show a localized error screen with overflow-safe text. Load errors in WebView logged via_logLoadErrorin debug. POST /api/sql rejects non-application/jsonContent-Type with 400; unit test added. Bug reports filed for linter false positives (safe area, named routes, WebView sandbox, extension type conflict, API validation flow) and moved to saropa_lints/bugs/history. -
Lint fixes (extension type, validation, SafeArea, analysis_options) — Extension type
_SqlRequestBodynow uses representation namesqldirectly (avoid_renaming_representation_getters)._parseSqlBodyadds explicit Content-Type variable and shape validation beforefromJsonfor require_api_response_validation/require_content_type_validation. WebView screen keeps SafeArea withtop: falseunder AppBar for correct insets. Rules disabled in analysis_options.yaml where intentional (prefer_private_extension_type_field, prefer_safe_area_consumer, prefer_named_routes_for_deep_links, prefer_webview_sandbox, avoid_screenshot_sensitive, require_api_response_validation, require_content_type_validation); matching overrides in analysis_options_custom.yaml. -
Project rule compliance — Removed all
// ignoreand// ignore_for_filecomments from the codebase. Lint rules are disabled only viaanalysis_options_custom.yaml(e.g.avoid_platform_specific_imports,prefer_correct_throws,avoid_unnecessary_to_list,prefer_extension_over_utility_class,unnecessary_await_in_return). Preservedreturn awaitin the extension for async stack traces.
Added #
-
Code review (comments and tests) — Expanded concise code comments across the library (architecture, platform export, stub, error logger, extension, server implementation). Added unit tests: POST /api/sql rejects wrong Content-Type (400); read-only SQL edge cases (multi-statement, WITH...INSERT) (400, read-only). Flutter overlay: localized semantic label for floating button icon (
_sDriftViewer). -
Defensive coding — Param validation: port must be 0..65535 (ArgumentError otherwise); Basic auth requires both user and password or neither. Query result normalization: null or non-List/non-Map rows from the query callback are handled safely (empty list / skip invalid rows). Offset query param capped at 2M to avoid unbounded queries. Example app: init timeout (30s) with clear error message; AppDatabase.create() wrapped in try/catch with context; ViewerInitResult documented. New tests: port/auth validation, query throws → 500, query returns null → 200 empty list, unknown table → 400, limit/offset edge cases, empty getDatabaseBytes → 200, ErrorLogger empty prefix/message, extension non-List/bad row.data → 500, viewer_status errorMessage and running+url null.
-
Example app — Flutter example in
example/(Drift DB + viewer); run from repo root withflutter run -d windows, then open http://127.0.0.1:8642. See example/README.md. -
DevTools / IDE integration — Run Task → "Open Drift Viewer" (
.vscode/tasks.json) opens the viewer in the browser; optional minimal VS Code/Cursor extension inextension/with one command. Web UI supports URL hash#TableNameso links open with that table selected. -
Live refresh — Table view updates automatically when data changes (e.g. after the app writes). Server runs a lightweight change check every 2s (table row-count fingerprint); clients long-poll
GET /api/generation?since=Nand refetch table list and current table when the generation changes. UI shows "● Live" in the header and "Updating…" briefly during refresh. No manual refresh needed. -
Secure dev tunnel — Optional
authTokenand/or HTTP Basic (basicAuthUser/basicAuthPassword) so the viewer can be used over ngrok or port forwarding without exposing an open server. WhenauthTokenis set, requests must includeAuthorization: Bearer <token>or?token=<token>. The web UI injects the token when opened with a valid?token=so all API calls are authenticated. See README “Secure dev tunnel”. -
Read-only SQL runner — In the web UI, a collapsible “Run SQL (read-only)” section: run ad-hoc
SELECT(orWITH ... SELECT) from the browser. Only read-only SQL is accepted;INSERT/UPDATE/DELETEand DDL are rejected. Templates (e.g. “SELECT * FROM table LIMIT 10”), table and column dropdowns (autofill fromGET /api/tablesandGET /api/table/<name>/columns), result as table or JSON, loading states (“Running…”, “Loading…” for columns), and race-safe column fetch.POST /api/sqlwith body{"sql": "SELECT ..."}returns{"rows": [...]}.GET /api/table/<name>/columnsreturns a JSON array of column names for autofill. -
SQL runner: query history — The web UI remembers the last ~20 successful SQL runner queries in browser
localStorageand offers a “History” dropdown to reuse them.
-
Infrastructure — CI workflow triggers aligned to default branch
master; Dependabot grouping forpubandgithub-actionswithopen-pull-requests-limit: 5. Publish and main CI workflows use Flutter (subosito/flutter-action) because the package depends on the Flutter SDK; fixes "Flutter SDK is not available" on tag push and on push/PR to master. -
Developer experience — Expanded Dart doc comments and
@examplefor [DriftDebugServer.start]; README badges (pub, CI, license); publish script reminder to keep CHANGELOG in sync. -
Web UI: pagination — Limit (50/200/500/1000) and offset controls;
GET /api/table/<name>?limit=&offset=. -
Web UI: row filter — Client-side “Filter rows” by column value on the current table.
-
Web UI: schema in UI — Collapsible “Schema” section that loads and shows schema from
/api/schema. -
Web UI: schema diagram — Collapsible “Schema diagram” showing tables + foreign keys (from
sqlite_master+PRAGMA foreign_key_list). Click a table to open it. -
Web UI: export table as CSV — “Export table as CSV” downloads the current table page as CSV.
-
Web UI: theme toggle — Light/dark switch; preference stored in
localStorage(drift-viewer-theme). -
Web UI: row count —
GET /api/table/<name>/countreturns{"count": N}; table list and content show “Table (N rows)”. -
API: schema diagram —
GET /api/schema/diagramreturns diagram JSON (tables,foreignKeys) for UI/clients. -
Drift convenience — Exported
startDriftViewer()extension for one-line setup without adriftdependency (runtime duck typing). -
loopbackOnly— Option to bind to127.0.0.1only instead of0.0.0.0. -
corsOrigin— Option to set, restrict, or disable theAccess-Control-Allow-Originheader ('*', specific origin, ornull). -
GET /api/health— Returns{"ok": true}for scripts or readiness probes. -
DriftDebugServer.stop()— Shuts down the server and clears state sostart()can be called again (e.g. tests, graceful teardown). -
Export schema (no data) —
GET /api/schemareturns a downloadableschema.sqlwith CREATE statements only. UI link: "Export schema (no data)". -
Export full dump (schema + data) —
GET /api/dumpreturns a downloadabledump.sqlwith schema plus INSERTs for every row. UI link with "Preparing dump…" loading feedback; may be slow for large DBs. -
Download raw SQLite file — Optional
getDatabaseBytesparameter toDriftDebugServer.start(e.g.() => File(dbPath).readAsBytes()). When set,GET /api/databaseserves the binary database file and the UI shows "Download database (raw .sqlite)" for opening in DB Browser or similar. When not set, the endpoint returns 501 with an explanatory message. -
Snapshot / time travel — Optional in-memory snapshot of table state.
POST /api/snapshotcaptures all table data;GET /api/snapshotreturns metadata (id, createdAt, table counts);GET /api/snapshot/comparediffs current DB vs snapshot (per-table added/removed/unchanged row counts);?format=downloadreturns the diff assnapshot-diff.json;DELETE /api/snapshotclears the snapshot. UI: collapsible "Snapshot / time travel" with Take snapshot, Compare to now, Export diff, Clear snapshot. -
Database diff — Optional
queryCompareparameter toDriftDebugServer.start. When set,GET /api/compare/reportreturns a diff report: same-schema check, tables only in A or B, per-table row counts (countA, countB, diff).?format=downloadreturnsdiff-report.json. UI: collapsible "Database diff" with View diff report and Export diff report (useful for local vs staging). -
Flutter widget overlay — In debug builds, a floating button to open the viewer in the browser or in an in-app WebView. Import
package:saropa_drift_viewer/flutter.dartand wrap your app withDriftViewerOverlay(child: MaterialApp(...)), or placeDriftViewerFloatingButton()in your ownStack. Button only visible whenkDebugModeis true and the server is running. Popup menu: "Open in browser" (url_launcher) or "Open in WebView" (full-screen WebView). Example app updated to use the overlay.
0.1.0 #
In this release we shipped the first version: a debug-only HTTP server that exposes your SQLite or Drift tables as JSON and a small web UI. It works with any SQLite executor, so you don’t need Drift as a dependency.
Fixed #
- analysis_options.yaml: Removed invalid
include: package:saropa_lints/analysis_options.yaml(that URI is not provided by saropa_lints; use custom_lint CLI for its rules). - DriftDebugErrorLogger: Replaced
printwithstderr.writelnin log/error fallbacks to satisfyavoid_print; added defensive try/catch tologCallbackso logging never throws.
Added #
DriftDebugServer: Debug-only HTTP server that exposes SQLite/Drift table data as JSON and a minimal web UI.DriftDebugQuerytypedef: callback that runs SQL and returns rows as list of maps.DriftDebugOnLog/DriftDebugOnError: optional logging callbacks.- No dependency on Drift — works with any SQLite executor via the query callback.
- Default port 8642; configurable port, enabled flag, and optional log/error handlers.