Public
HTTP (deprecated)
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Readme

SQLite Explorer

View and interact with your Val Town SQLite data. It's based off Steve's excellent SQLite Admin val, adding the ability to run SQLite queries directly in the interface. This new version has a revised UI and that's heavily inspired by LibSQL Studio by invisal. This is now more an SPA, with tables, queries and results showing up on the same page.

image.webp

Install

Install the latest stable version (v37) by forking this val that imports & exports it in your account:

Install v37

Authentication

SQLite Explorer basic authentication with your Val Town API Token as the password (leave the username field blank).

Todos / Plans

  • fix wonky sidebar separator height problem
  • improve error handling
  • improve table formatting
  • make result tables scrollable
  • add codemirror
  • add loading indication to the run button (initial version shipped)
  • add ability to favorite queries
  • add saving of last query run for a table (started)
  • add visible output for non-query statements
  • add schema viewing
  • add export to CSV, and JSON (CSV and JSON helper functions written in this val)
  • add export to sqlite
  • add refresh to table list sidebar after CREATE/DROP/ALTER statements
  • add automatic execution of initial select query on double click
  • add listener for cmd+enter to submit query
  • add views to the sidebar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/** @jsxImportSource https://esm.sh/hono@latest/jsx **/
import { resetStyle } from "https://esm.town/v/nbbaier/resetStyle";
import { sqlToCSV, sqlToJSON } from "https://esm.town/v/nbbaier/sqliteExportHelpers?v=4";
import {
EditorSection,
MockTable,
Separator,
Table,
TablesList,
} from "https://esm.town/v/nbbaier/sqliteStudioComponents";
import { RunSVG, TableSVG } from "https://esm.town/v/nbbaier/sqliteStudioSVGs";
import { sqliteStyle } from "https://esm.town/v/nbbaier/sqliteStyle";
import { basicAuth } from "https://esm.town/v/pomdtr/basicAuth";
import { sqlite } from "https://esm.town/v/std/sqlite";
import { Hono } from "npm:hono";
import type { FC } from "npm:hono/jsx";
import { jsxRenderer } from "npm:hono/jsx-renderer";
const HTML: FC = ({ children }) => {
return (
<html>
<head>
<title>SQLite Explorer</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap"
rel="stylesheet"
/>
<style
dangerouslySetInnerHTML={{ __html: resetStyle }}
/>
<style
dangerouslySetInnerHTML={{ __html: sqliteStyle }}
/>
<script src="https://unpkg.com/htmx.org@1.9.9/dist/htmx.min.js"></script>
<script src="https://unpkg.com/hyperscript.org@0.9.12"></script>
<script type="module" src="https://esm.town/v/nbbaier/resizeScript" />
<script type="module" src="https://esm.town/v/nbbaier/tableSelectScript" />
</head>
<body _="
on keydown[event.metaKey and key is 'Enter'] log 'command + enter' then send submitForm to #sql-editor
">
<div class="root-container">
<header>
<h1>sqlite explorer</h1>
</header>
{children}
</div>
</body>
</html>
);
};
const app = new Hono();
app.use(
"*",
jsxRenderer(
({ children }) => {
return <HTML children={children} />;
},
{ docType: false },
),
);
app.get("/", async (c) => {
let data = await sqlite.execute(`
SELECT
name
FROM
sqlite_schema
WHERE
type ='table' AND
name NOT LIKE 'sqlite_%';`);
let tables = data.rows;
return c.render(
<main class="sidebar-layout">
<div class="sidebar">
<TablesList tables={tables}></TablesList>
</div>
<Separator direction="horizontal"></Separator>
<div class="not-sidebar">
<EditorSection />
<Separator direction="vertical" isResizer={true}></Separator>
<div class="bottom-container">
<div id="results-table" class="bottom">
</div>
</div>
</div>
</main>,
);
});
app.post("/query", async (c) => {
const query = (await c.req.parseBody()).query as string;
try {
console.log(`attempting:`, query);
const rs = await sqlite.execute(query);
pomdtr-sqliteexplorerapp.web.val.run
February 28, 2024