3 sqlite as valTownSqlite,
4} from "https://esm.town/v/stevekrouse/sqlite";
5// import { BindParameters, Database } from "https://deno.land/x/sqlite3/mod.ts";
6
7export interface QueryResult {
10}
11
12export interface DatabaseClient {
13 execute(query: string, params?: unknown[]): Promise<QueryResult>;
14}
15
16class ValTownDatabaseClient implements DatabaseClient {
17 async execute(query: string, params: InValue[] = []): Promise<QueryResult> {
18 const result = await valTownSqlite.execute(query, params);
24}
25
26// class LocalDatabaseClient implements DatabaseClient {
27// private db: Database;
28
29// constructor(dbPath: string) {
30// this.db = new Database(dbPath);
31// }
32
48// }
49
50// Factory function to create the appropriate database client
51export function createDatabaseClient(): DatabaseClient {
52 // Check if we're running in Val Town
53 // const isValTown = Deno.env.get("VAL_TOWN") === "true";
54
55 // if (isValTown) {
56 return new ValTownDatabaseClient();
57 // } else {
58 // For local development, use a file-based SQLite database
59 // const dbPath = Deno.env.get("DB_PATH") || "./local.db";
60 // return new LocalDatabaseClient(dbPath);
61 // }
62}
63
64// Export a singleton instance
65export const db = createDatabaseClient();
66
192```
193βββ backend/
194β βββ database/
195β β βββ migrations.ts # Schema definitions
196β β βββ queries.ts # DB query functions
252 ```
253
254### Database Patterns
255- Run migrations on startup or comment out for performance
256- Change table names when modifying schemas rather than altering
1// Quiz questions database
2const QUIZ_QUESTIONS = [
3 { question: "Is the Earth round?", answer: true, type: "true/false" },
12});
13
14// Database setup with new schema version
15const REQUESTS_TABLE = 'screen_composer_requests_2';
16const LABELS_TABLE = 'screen_composer_labels_1';
17const APPS_TABLE = 'screen_composer_apps_1';
18
19// Initialize database tables
20try {
21 await sqlite.execute(`CREATE TABLE IF NOT EXISTS ${REQUESTS_TABLE} (
59 }
60
61 console.log("Database initialization completed successfully");
62} catch (error) {
63 console.error("Database initialization error:", error);
64}
65
344 } catch (error) {
345 console.error("Error preparing browser response:", error);
346 // Continue with basic HTML if database fails
347 }
348
21## Further resources
22
23- [React Hono Example](https://www.val.town/x/stevekrouse/reactHonoExample) is a bigger example project, with a SQLite database table, queries, client-side CSS, a favicon, and shared code that runs on both client and server.
47 "slug": "codegen",
48 "link": "/blog/codegen",
49 "description": "Like Claude Artifacts, but with a backend and database",
50 "pubDate": "Thu, 22 Aug 2024 00:00:00 GMT",
51 "author": "JP Posma",
198```
199βββ backend/
200β βββ database/
201β β βββ migrations.ts # Schema definitions
202β β βββ queries.ts # DB query functions
257 ```
258
259### Database Patterns
260- Run migrations on startup or comment out for performance
261- Change table names when modifying schemas rather than altering
1---
2title: "Post-mortem: A Backward Incompatible Database Migration"
3description: Val runs failed due to a database migration that was not backward compatible
4pubDate: 2025-04-02T00:00:00.000Z
5author: Sophie Houser
8Today at 10:11am we experienced a 12-minute outage, which caused HTTP vals to
9return 503 errors and other types of vals to fail. In the end, the root cause
10was a deployment timing issue where database migrations were deployed
11successfully, but our application code deployment hung for several minutes. The
12new database migrations were incompatible with the old application code and
13crashed the process.
14
15We aim to make all database migrations maintain backward compatibility, but in
16this case, we only discovered through the delayed deployment feedback that the
17new migrations were not compatible with previous versions.
39
40Reliability is important to us and weβve taken steps to make sure this doesnβt
41happen again. Weβve added a test to ensure database migrations are backward
42compatible, which weβll run before we deploy any new code that includes database
43migrations.
44
17
18π **Request Logging**
19- SQLite database for persistent storage
20- Logs all device interactions with timestamps
21- Shows request/response pairs for debugging
3const TABLE_NAME = 'webhook_logs';
4
5// Initialize the database table
6async function initDB() {
7 await sqlite.execute(`CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
84 ip: ip
85 },
86 log_id: null, // Will be filled by the database
87 next_steps: 'Visit the webhook catcher URL in your browser to view all logged requests'
88 }), {