Vals using @libsql/client
Val Town SQLite - https://docs.val.town/std/sqlite
sqliteBuilder: Opinionated safe(r) query builder using tagged templates
Create valimport { Statement } from "https://esm.town/v/postpostscript/sqliteBuilder";
const unsafeId = "1234 or TRUE"
console.log(Statement`
SELECT *
FROM table
WHERE id = ${unsafeId}
${Statement`AND other_`}
`)
// StatementInstance {
// sql: "\nSELECT *\nFROM table\nWHERE id = ?\nAND otherCondition\n",
// args: [ "1234 or TRUE" ],
// log: false
// }
const results = await Statement`SELECT ...`.execute()
// [ { key: "value", anotherKey: "anotherValue" }, ... ]
Or you can pass it directly to @std/sqlite.execute
:
Create valimport { sqlite } from "https://esm.town/v/std/sqlite"
await sqlite.execute(Statement`Select ...`)
You can combine multiple statements using Statement.prototype.combineWith
:
Statement`...`.combineWith(Statement`...`, " AND ")
[
Statement`fieldA`,
Statement`fieldB`,
Statement`fieldC`,
].reduce((a, b) => a.combineWith(b, ", "))
Query All Public Vals
Example: val town leaderboard
Create valimport { zip } from "https://esm.town/v/pomdtr/sql";
import { db } from "https://esm.town/v/sqlite/db";
const res = await db.execute("SELECT author_username, COUNT(*) AS val_count FROM vals GROUP BY author_username ORDER BY 2 DESC LIMIT 10");
console.table(zip(res));
sqliteUniverse: make queries against multiple vals or endpoints at the same time!
Example: @postpostscript/sqliteUniverseExample
Todo
- tests‼️
- update to support following syntax:
SELECT * FROM "@example/endpoint".someTable
orSELECT * FROM "@example/endpoint:::someTable"
sqliteBuilder: Opinionated safe(r) query builder using tagged templates
Create valimport { Statement } from "https://esm.town/v/postpostscript/sqliteBuilder";
const unsafeId = "1234 or TRUE"
console.log(Statement`
SELECT *
FROM table
WHERE id = ${unsafeId}
${Statement`AND other_`}
`)
// StatementInstance {
// sql: "\nSELECT *\nFROM table\nWHERE id = ?\nAND otherCondition\n",
// args: [ "1234 or TRUE" ],
// log: false
// }
const results = await Statement`SELECT ...`.execute()
// [ { key: "value", anotherKey: "anotherValue" }, ... ]
Or you can pass it directly to @std/sqlite.execute
:
Create valimport { sqlite } from "https://esm.town/v/std/sqlite"
await sqlite.execute(Statement`Select ...`)
You can combine multiple statements using Statement.prototype.combineWith
:
Statement`...`.combineWith(Statement`...`, " AND ")
[
Statement`fieldA`,
Statement`fieldB`,
Statement`fieldC`,
].reduce((a, b) => a.combineWith(b, ", "))
SQLite Table Export Utils
This allows for a val.town-hosted SQLite table to be exported as:
- JSON (
Record<string, unknown>[]
) - Arrow IPC (
Uint8Array
) - TODO: Others?
This can then be used by a HTTP endpoint, like so:
Create valimport { exportSQLiteTable, SQLiteTableExportFormat } from "https://esm.town/v/rlesser/sqliteTableExportUtils";
export default async function(req: Request): Promise<Response> {
const tableName = new URL(req.url).searchParams.get("table");
if (!tableName) {
return new Response("Table name is required", { status: 400 });
}
const format = (new URL(req.url).searchParams.get("format") || "arrowIPC") as SQLiteTableExportFormat;
const data = await exportSQLiteTable(tableName, format);
if (data instanceof Uint8Array) {
return new Response(data, {
headers: { "Content-Type": "application/octet-stream" },
});
} else {
return Response.json(data);
}
}
TODO
- Specify limit and offset of export, for pagination
- Smart assessment of if the export is going to be over the val.town limit of 10MB, adjust to paginated of so.
- Support other export formats.
PRs welcome!
SQLite Table Export Utils
This allows for a val.town-hosted SQLite table to be exported as:
- JSON (
Record<string, unknown>[]
) - Arrow IPC (
Uint8Array
) - TODO: Others?
This can then be used by a HTTP endpoint, like so:
Create valimport { exportSQLiteTable, SQLiteTableExportFormat } from "https://esm.town/v/rlesser/sqliteTableExportUtils";
export default async function(req: Request): Promise<Response> {
const tableName = new URL(req.url).searchParams.get("table");
if (!tableName) {
return new Response("Table name is required", { status: 400 });
}
const format = (new URL(req.url).searchParams.get("format") || "arrowIPC") as SQLiteTableExportFormat;
const data = await exportSQLiteTable(tableName, format);
if (data instanceof Uint8Array) {
return new Response(data, {
headers: { "Content-Type": "application/octet-stream" },
});
} else {
return Response.json(data);
}
}
TODO
- Specify limit and offset of export, for pagination
- Smart assessment of if the export is going to be over the val.town limit of 10MB, adjust to paginated of so.
- Support other export formats.
PRs welcome!
This is a wrapper of the val town std sqlite library that adds tracing via https://www.val.town/v/saolsen/tracing.
Val Town SQLite
SQLite - Docs ↗
SQLite is a lightweight, standard database. Every Val Town account comes with its own private SQLite database that is accessible from any of your vals via std/sqlite
.
Val Town SQLite is powered by Turso.
You may find these admin viewers helpful managing your database:
- SQLite Explorer (built in Val Town)
- LibSQL Studio
Limits
You can store 10mb on the free plan and up to 1gb on the paid plan. Contact us if you need more space.