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

DuckDB

DuckDB works on Val Town, with only one small tweak! We're basically using DuckDB in the same way you'd use it with a browser - using the WASM package with its dependencies fetched from jsdelivr.

The only trick is to create the worker ourselves rather than using duckdb.createWorker. DuckDB's built-in createWorker method doesn't specify a worker type, which causes type to default to classic, and Deno (our runtime) doesn't support classic workers.

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
import { fetch } from "https://esm.town/v/std/fetch";
export let duckdbExample = (async () => {
async function createWorker(url: string) {
const workerScript = await fetch(url);
const workerURL = URL.createObjectURL(await workerScript.blob());
return new Worker(workerURL, { type: "module" });
}
const duckdb = await import(
"https://cdn.jsdelivr.net/npm/@duckdb/duckdb-wasm@1.17.0/+esm"
);
const bundles = duckdb.getJsDelivrBundles();
const bundle = await duckdb.selectBundle(bundles);
const logger = new duckdb.ConsoleLogger();
const worker = await createWorker(bundle.mainWorker);
const db = new duckdb.AsyncDuckDB(logger, worker);
await db.instantiate(bundle.mainModule);
const c = await db.connect();
const res = await c.query(`SELECT * FROM generate_series(1, 100) t(v)`);
c.close();
db.terminate();
// DuckDB's toJSON unfortunately includes BigInts, and we can't serialize
// BigInts because they have no basic JSON representation. So,
// Translate them to ints.
return res.toArray().map((r) => {
const row = r.toJSON();
return JSON.parse(JSON.stringify(row, (k, v) => {
return typeof v === "bigint" ? +v.toString() : v;
}));
});
})();
October 23, 2023