1import { Hono } from "https://esm.sh/hono@3.11.7";
2import { runMigrations } from "./database/migrations.ts";
3import * as db from "./database/queries.ts";
4import games from "./routes/games.ts";
5import scoring from "./routes/scoring.ts";
14});
1516// Initialize database on startup
17await runMigrations();
18
1098<div style="background-color: #FFFFFF; border: 1px solid #ccc; padding: 16px; border-radius: 8px; margin: 20px 0;">
1099<p><strong>CSV Format:</strong> The file should have columns: Name, Email, Signed At</p>
1100<p><strong>Note:</strong> This will add signatures to the existing database. Duplicates based on email will be skipped.</p>
1101</div>
1102
1import { Hono } from "https://esm.sh/hono@3.11.7";
2import { readFile, serveFile } from "https://esm.town/v/std/utils/index.ts";
3import * as db from "../database/queries.ts";
45const staticRoutes = new Hono();
1import { Hono } from "https://esm.sh/hono@3.11.7";
2import type { CreateGameRequest, ApiResponse, Game } from "../../shared/types.ts";
3import * as db from "../database/queries.ts";
45const games = new Hono();
screenmigrations.ts3 matches
1import { sqlite } from "https://esm.town/v/stevekrouse/sqlite";
23// Database schema for pickleball scoring app
4export async function runMigrations() {
5console.log("Running database migrations...");
67// Sites table
84await insertDefaultData();
85
86console.log("Database migrations completed successfully");
87}
88
23```
24βββ backend/
25β βββ database/
26β β βββ migrations.ts # Database schema
27β β βββ queries.ts # Database operations
28β βββ routes/
29β β βββ games.ts # Game management API
we-the-undersignedREADME.md8 matches
1# Hello SQLite!
23This project includes a [Node.js](https://nodejs.org/en/about/) server script that uses a persistent [SQLite](https://www.sqlite.org) database. The app also includes a front-end with two web pages that connect to the database using the server API. π
45The home page presents the user with a poll where they can choose an option, then the page presents the results in a chart. The admin page displays the log of past choices and allows the user to clear it by supplying an admin key (you can set this up by following the steps in `TODO.md`). π
19β `.env`: The environment is cleared when you initially remix the project, but you will add a new env variable value when you follow the steps in `TODO.md` to set up an admin key.
2021### Server and database
2223β `server.js`: The Node.js server script for your new site. The JavaScript defines the endpoints in the site API. The API processes requests, connects to the database using the `sqlite` script in `src`, and sends info back to the client (the web pages that make up the app user interface, built using the Handlebars templates in `src/pages`).
2425β `/src/sqlite.js`: The database script handles setting up and connecting to the SQLite database. The `server.js` API endpoints call the functions in the database script to manage the data.
2627β `/src/data.json`: The data config file includes the database manager scriptβ`server.js` reads the `database` property to import the correct script.
2829When the app runs, the scripts build the database:
3031β `.data/choices.db`: Your database is created and placed in the `.data` folder, a hidden directory whose contents arenβt copied when a project is remixed. You can see the contents of `.data` in the console by selecting __Tools__ > __Logs__.
3233### User interface
37β `src/pages`: The handlebars files that make up the site user interface. The API in `server.js` sends data to these templates to include in the HTML.
3839β `src/pages/index.hbs`: The site homepage presents a form when the user first visits. When the visitor submits a preference through the form, the app calls the `POST` endpoint `/`, passing the user selection. The `server.js` endpoint updates the database and returns the user choices submitted so far, which the page presents in a chart (using [Chart.js](https://www.chartjs.org/docs/)βyou can see the code in the page `head`).
4041β `src/pages/admin.hbs`: The admin page presents a table displaying the log of most recent picks. You can clear the list by setting up your admin key (see `TODO.md`). If the user attempts to clear the list without a valid key, the page will present the log again.
we-the-undersignedsqlite.ts20 matches
1/**
2* Module handles database management
3*
4* Server API calls the methods in here to query and update the SQLite database
5*/
67// Utilities we need
8import * as fs from "fs";
9import { Database, open } from "sqlite";
10import * as sqlite3 from "sqlite3";
1124}
2526interface DatabaseInterface {
27getSubmissions(): Promise<Submission[] | null>;
28processSubmission(name: string, email: string): Promise<Submission[] | null>;
34}
3536// Initialize the database
37const dbFile: string = "./.data/signatures.db";
38const exists: boolean = fs.existsSync(dbFile);
39let db: Database<sqlite3.Database, sqlite3.Statement>;
4041/*
43- https://www.npmjs.com/package/sqlite
44*/
45const initializeDatabase = async (): Promise<void> => {
46try {
47db = await open({
48filename: dbFile,
49driver: sqlite3.Database,
50});
5152// We use try and catch blocks throughout to handle any database errors
53try {
54// The async / await syntax lets us write the db operations in a way that won't block the app
55if (!exists) {
56// Database doesn't exist yet - create Submissions and Log tables
57await db.run(
58"CREATE TABLE Submissions (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, email TEXT, created TEXT)",
74await db.run(
75"INSERT INTO Log (action, timestamp) VALUES (?, ?)",
76["Database initialized with sample signatures", currentTime],
77);
78} else {
79// We have a database already - write Submissions records to log for info
80const existingSubmissions: Partial<Submission>[] = await db.all("SELECT id, name, created from Submissions");
81console.log(existingSubmissions);
85}
86} catch (error) {
87console.error("Failed to initialize database:", error);
88}
89};
9091// Initialize the database connection
92initializeDatabase();
9394// Our server script will call these methods to connect to the db
95const databaseModule: DatabaseInterface = {
96/**
97* Get the submissions in the database
98*
99* Return everything in the Submissions table
106return submissions;
107} catch (dbError) {
108// Database connection error
109console.error(dbError);
110return null;
149*
150* Receive the signature ID from server
151* Remove the signature from the database
152* Add a log entry
153* Return success/failure flag
267};
268269export = databaseModule;
we-the-undersigneddata.json3 matches
1{
2"database": "sqlite.js",
3"errorMessage": "Whoops! Error connecting to the databaseβplease try again!",
4"setupMessage": "π§ Whoops! Looks like the database isn't setup yet! π§"
5}
we-the-undersignedserver.ts15 matches
1/**
2* This is the main server script that provides the API endpoints
3* The script uses the database helper in /src
4* The endpoints retrieve, update, and return data to the page handlebars files
5*
26}
2728interface DatabaseConfig {
29database: string;
30errorMessage: string;
31setupMessage: string;
45}
4647interface DatabaseInterface {
48getSubmissions(): Promise<Submission[] | false>;
49processSubmission(name: string, email: string): Promise<Submission[] | false>;
114}
115116// We use a module for handling database operations in /src
117const data: DatabaseConfig = require("./src/data.json");
118const db: DatabaseInterface = require("./src/" + data.database);
119120/**
121* Home route for the app
122*
123* Return the form submissions from the database helper script
124* The home route may be called on remix in which case the db needs setup
125*
133let params: PageParams = request.query.raw ? {} : { seo: seo };
134135// Get the available submissions from the database
136const submissions: Submission[] | false = await db.getSubmissions();
137if (submissions) {
156*
157* Retrieve form data from body
158* Send data to database helper
159* Return updated list of submissions
160*/
176params.error = "Please complete the captcha";
177178// Get the available submissions from the database for display on the form page
179submissions = await db.getSubmissions();
180if (submissions) {
201params.error = "Captcha verification failed. Please try again.";
202203// Get the available submissions from the database for display on the form page
204submissions = await db.getSubmissions();
205if (submissions) {
214// Captcha verified! Continue with the form processing
215if (request.body.name && request.body.email) {
216// Process the submission with the database helper
217submissions = await db.processSubmission(request.body.name, request.body.email);
218if (submissions) {
224params.error = "Please provide both name and email.";
225226// Get the available submissions from the database for display on the form page
227submissions = await db.getSubmissions();
228if (submissions) {
235params.results = false;
236237// Get the available submissions from the database for display on the form page
238submissions = await db.getSubmissions();
239if (submissions) {