### Install and Run bun-poll Server Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Instructions to install Bun, clone the bun-poll repository, install dependencies, and start the development server with hot reloading. The server will be accessible at http://localhost:3000. ```bash # Install Bun if you haven't already curl -fsSL https://bun.sh/install | bash # Clone and install git clone https://github.com/danjdewhurst/bun-poll.git cd bun-poll bun install # Start the dev server with hot reload bun --hot index.ts # Server starts at http://localhost:3000 ``` -------------------------------- ### Install and Run bun-poll (Bash) Source: https://github.com/danjdewhurst/bun-poll/blob/main/README.md This snippet shows how to install Bun, clone the bun-poll repository, install its dependencies, and start the development server. It's the primary method for getting the application running locally. ```bash # Install Bun if you haven't already curl -fsSL https://bun.sh/install | bash # Clone and install git clone https://github.com/danjdewhurst/bun-poll.git cd bun-poll bun install # Start the dev server bun --hot index.ts ``` -------------------------------- ### Bun Frontend React Component Example Source: https://github.com/danjdewhurst/bun-poll/blob/main/CLAUDE.md A React component example for frontend development with Bun, demonstrating how to import React, use `createRoot`, and render a component. It also shows direct CSS import. ```tsx import React from "react"; import { createRoot } from "react-dom/client"; // import .css files directly and it works import './index.css'; const root = createRoot(document.body); export default function Frontend() { return

Hello, world!

; } root.render(); ``` -------------------------------- ### Install Bun Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/getting-started.md Installs the Bun JavaScript runtime. This is a prerequisite for the project. The command fetches and executes an installation script. ```bash # Install Bun if you haven't already curl -fsSL https://bun.sh/install | bash ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/getting-started.md Clones the bun-poll repository and installs its dependencies using Bun. The only dev dependency is `@types/bun` for TypeScript support, with no runtime dependencies. ```bash git clone https://github.com/danjdewhurst/bun-poll.git cd bun-poll bun install ``` -------------------------------- ### Example Poll Creation Test in TypeScript Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Demonstrates an example test case for the poll creation API endpoint using Bun's testing utilities. It sends a POST request to the '/api/polls' endpoint with poll data and asserts the expected response status and returned data, including 'share_id' and 'admin_id'. ```typescript // Example test for poll creation import { describe, expect, test } from "bun:test"; describe("POST /api/polls", () => { test("creates a poll and returns share_id + admin_id", async () => { const res = await fetch("http://localhost:3000/api/polls", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ question: "Favourite colour?", options: ["Red", "Blue", "Green"], }), }); expect(res.status).toBe(200); const data = await res.json(); expect(data.share_id).toBeString(); expect(data.share_id).toHaveLength(16); expect(data.admin_id).toBeString(); }); }); ``` -------------------------------- ### Bun Testing Example Source: https://github.com/danjdewhurst/bun-poll/blob/main/CLAUDE.md Demonstrates how to write and run tests using Bun's built-in testing framework. This replaces traditional testing tools like Jest or Vitest. ```typescript import { test, expect } from "bun:test"; test("hello world", () => { expect(1).toBe(1); }); ``` -------------------------------- ### Embedding Polls Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Provides instructions and examples for embedding polls into external web pages using iframes. ```APIDOC ## Embedding Polls ### Description Polls can be embedded into external websites using an iframe for a compact view. ### Endpoint `/embed/{pollId}` ### Parameters #### Path Parameters - **pollId** (string) - Required - The unique identifier of the poll to embed. ### Request Example ```html
``` ``` -------------------------------- ### Test Scheduled Polls Functionality Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/testing.md Tests the behavior of polls with scheduled start times. It verifies that polls can be created with a future `starts_at` time, that voting is blocked before the start time (returning 403), and that voting proceeds normally after the start time. ```typescript // Test creating a poll with a valid starts_at const futureDate = new Date(Date.now() + 60000); // 1 minute from now const poll = await createTestPoll({ starts_at: futureDate.toISOString() }); expect(poll.starts_at).toBe(futureDate.toISOString()); // Test voting blocked before start time await expect(fetch(`/api/polls/${poll.share_id}/vote`, { method: "POST", headers: { "Content-Type": "application/json", "X-Voter-Token": "pre_vote_token" }, body: JSON.stringify({ options: [poll.options[0].id] }) })).rejects.toThrow("403 Forbidden"); // Test voting allowed after start time (simulate time passing or adjust test) // await new Promise(resolve => setTimeout(resolve, 60000)); // Wait for start time // const voteResponse = await fetch(`/api/polls/${poll.share_id}/vote`, { // method: "POST", // headers: { // "Content-Type": "application/json", // "X-Voter-Token": "post_vote_token" // }, // body: JSON.stringify({ options: [poll.options[0].id] }) // }); // expect(voteResponse.status).toBe(200); ``` -------------------------------- ### Run Development Server Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/getting-started.md Starts the bun-poll server in development mode with hot module reloading enabled. The server defaults to http://localhost:3000. ```bash bun --hot index.ts ``` -------------------------------- ### Get Results Summary Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Retrieves a plain-text summary of poll results, suitable for sharing. ```APIDOC ## GET /api/polls/admin/{pollId}/summary ### Description Returns a plain-text summary of poll results. ### Method GET ### Endpoint `/api/polls/admin/{pollId}/summary` ### Parameters #### Path Parameters - **pollId** (string) - Required - The unique identifier of the poll. ### Response #### Success Response (200) - **(string)**: A formatted text summary of the poll question, options with votes and percentages, and total votes. ### Request Example ```bash curl http://localhost:3000/api/polls/admin/550e8400-e29b-41d4-a716-446655440000/summary ``` ### Response Example ```text Poll: What is your favourite programming language? TypeScript: 6 votes (40%) Rust: 3 votes (20%) Go: 2 votes (13.3%) Python: 4 votes (26.7%) Total: 15 votes ``` ``` -------------------------------- ### SQLite Database Setup and Prepared Statements in TypeScript Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Initializes an SQLite database with WAL mode for concurrent reads and defines tables for polls, options, and votes. It also includes prepared statements for efficient data insertion and retrieval, ensuring optimal performance. Dependencies include the 'bun:sqlite' module. ```typescript import { Database } from "bun:sqlite"; // Initialize database with WAL mode for concurrent reads const db = new Database("bun-poll.sqlite"); db.run("PRAGMA journal_mode = WAL"); db.run("PRAGMA foreign_keys = ON"); // Polls table db.run(` CREATE TABLE IF NOT EXISTS polls ( id INTEGER PRIMARY KEY AUTOINCREMENT, share_id TEXT NOT NULL UNIQUE, admin_id TEXT NOT NULL UNIQUE, question TEXT NOT NULL, allow_multiple INTEGER NOT NULL DEFAULT 0, starts_at INTEGER, expires_at INTEGER, created_at INTEGER NOT NULL ) `); // Options table with cascade delete db.run(` CREATE TABLE IF NOT EXISTS options ( id INTEGER PRIMARY KEY AUTOINCREMENT, poll_id INTEGER NOT NULL REFERENCES polls(id) ON DELETE CASCADE, text TEXT NOT NULL, position INTEGER NOT NULL DEFAULT 0 ) `); // Votes table with deduplication constraint db.run(` CREATE TABLE IF NOT EXISTS votes ( id INTEGER PRIMARY KEY AUTOINCREMENT, poll_id INTEGER NOT NULL REFERENCES polls(id) ON DELETE CASCADE, option_id INTEGER NOT NULL REFERENCES options(id) ON DELETE CASCADE, voter_token TEXT NOT NULL, voter_ip TEXT NOT NULL DEFAULT '', created_at INTEGER NOT NULL, UNIQUE(poll_id, option_id, voter_token) ) `); // Prepared statement for inserting a poll const insertPoll = db.prepare< { id: number; share_id: string; admin_id: string }, [string, string, string, number, number | null, number | null, number] >(` INSERT INTO polls (share_id, admin_id, question, allow_multiple, starts_at, expires_at, created_at) VALUES (?, ?, ?, ?, ?, ?, ?) RETURNING id, share_id, admin_id `); // Get poll results with vote counts const getResultsByPollId = db.prepare< { id: number; poll_id: number; text: string; position: number; votes: number }, [number] >(` SELECT o.*, COALESCE(v.cnt, 0) AS votes FROM options o LEFT JOIN (SELECT option_id, COUNT(*) AS cnt FROM votes GROUP BY option_id) v ON v.option_id = o.id WHERE o.poll_id = ? ORDER BY o.position `); ``` -------------------------------- ### GET /health - Health Check Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/testing.md Performs a health check on the application. Returns the application status, uptime, and database connection status. ```APIDOC ## GET /health ### Description Checks the health status of the application, including uptime and database connectivity. ### Method GET ### Endpoint /health ### Parameters None ### Response #### Success Response (200) - **status** (string) - The overall health status (e.g., "ok"). - **uptime_seconds** (integer) - The number of seconds the application has been running. - **polls** (integer) - The current count of active polls. - **database** (string) - The status of the database connection (e.g., "ok"). #### Response Example ```json { "status": "ok", "uptime_seconds": 3600, "polls": 15, "database": "ok" } ``` ``` -------------------------------- ### Create a New Poll via API Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Demonstrates how to create a new poll using the /api/polls endpoint with various options such as multiple choice and scheduled start times. The API returns unique share and admin IDs for the created poll. ```bash # Create a basic poll curl -X POST http://localhost:3000/api/polls \ -H "Content-Type: application/json" \ -d '{ "question": "What is your favourite programming language?", "options": ["TypeScript", "Rust", "Go", "Python"] }' # Response: {"share_id":"a1b2c3d4e5f6g7h8","admin_id":"550e8400-e29b-41d4-a716-446655440000"} # Create a poll with multiple choice and expiration curl -X POST http://localhost:3000/api/polls \ -H "Content-Type: application/json" \ -d '{ "question": "Which frameworks have you used?", "options": ["React", "Vue", "Angular", "Svelte"], "allow_multiple": true, "expires_in_minutes": 60 }' # Create a scheduled poll that opens in the future curl -X POST http://localhost:3000/api/polls \ -H "Content-Type: application/json" \ -d '{ "question": "Team lunch preference?", "options": ["Pizza", "Sushi", "Tacos"], "starts_at": "2026-03-01T12:00:00Z", "expires_in_minutes": 1440 }' ``` -------------------------------- ### POST /api/polls Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/api.md Creates a new poll with a question, options, and optional settings like multiple selections, expiry, and start time. ```APIDOC ## POST /api/polls ### Description Creates a new poll with a question, options, and optional settings like multiple selections, expiry, and start time. ### Method POST ### Endpoint /api/polls ### Parameters #### Request Body - **question** (string) - Required - The poll question (non-empty after trim, max 500 characters) - **options** (string[]) - Required - 2–20 option labels (each non-empty after trim, max 200 characters) - **allow_multiple** (boolean) - Optional - Allow voters to select more than one option (default `false`) - **expires_in_minutes** (number) - Optional - Minutes until voting closes (omit for no expiry) - **starts_at** (string) - Optional - ISO 8601 date-time when voting opens (omit to start immediately) ### Request Example ```json { "question": "Favourite language?", "options": ["TypeScript", "Rust", "Go"], "allow_multiple": false, "expires_in_minutes": 60 } ``` ### Response #### Success Response (200) - **share_id** (string) - 8-character hex string used in voting links - **admin_id** (string) - UUID v4 used in the admin link (keep private) #### Response Example ```json { "share_id": "a1b2c3d4", "admin_id": "550e8400-e29b-41d4-a716-446655440000" } ``` ### Errors - `400` - Empty question, question exceeds 500 characters, fewer than 2 options, more than 20 options, empty option string, or option exceeds 200 characters - `400` - Invalid `starts_at` date, `starts_at` is in the past, or `starts_at` is not before `expires_at` - `500` - Database insert failure ``` -------------------------------- ### GET /api/polls/admin/:adminId/summary Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/api.md Returns a plain-text summary of poll results suitable for pasting into chat or email. ```APIDOC ## GET /api/polls/admin/:adminId/summary ### Description Returns a plain-text summary of poll results suitable for pasting into chat or email. ### Method GET ### Endpoint `/api/polls/admin/:adminId/summary` ### Response #### Success Response (200) - **Content-Type**: `text/plain` #### Response Example ``` Poll: Favourite language? TypeScript: 3 votes (60%) Rust: 1 votes (20%) Go: 1 votes (20%) Total: 5 votes ``` #### Error Response (404) - **Reason**: Poll not found ``` -------------------------------- ### Get Poll Details Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Retrieves poll data including current vote counts. Pass a voter token to check if the user has already voted. ```APIDOC ## GET /api/polls/{share_id} ### Description Retrieves poll data including current vote counts. Pass a voter token to check if the user has already voted. ### Method GET ### Endpoint /api/polls/{share_id} ### Parameters #### Path Parameters - **share_id** (string) - Required - The unique ID of the poll to retrieve. #### Query Parameters - **voter_token** (string) - Optional - A token to identify the voter and check if they have already voted. ### Response #### Success Response (200) - **poll** (object) - Details about the poll. - **share_id** (string) - **question** (string) - **allow_multiple** (integer) - **starts_at** (string | null) - **expires_at** (string | null) - **created_at** (integer) - **options** (array of objects) - Details about each poll option. - **id** (integer) - **poll_id** (integer) - **text** (string) - **position** (integer) - **votes** (integer) - **total_votes** (integer) - The total number of votes cast for the poll. - **has_voted** (boolean) - Whether the current voter (identified by voter_token) has voted. #### Response Example ```json { "poll": { "share_id": "a1b2c3d4e5f6g7h8", "question": "What is your favourite programming language?", "allow_multiple": 0, "starts_at": null, "expires_at": null, "created_at": 1700000000000 }, "options": [ {"id": 1, "poll_id": 1, "text": "TypeScript", "position": 0, "votes": 5}, {"id": 2, "poll_id": 1, "text": "Rust", "position": 1, "votes": 3}, {"id": 3, "poll_id": 1, "text": "Go", "position": 2, "votes": 2}, {"id": 4, "poll_id": 1, "text": "Python", "position": 3, "votes": 4} ], "total_votes": 14, "has_voted": false } ``` ``` -------------------------------- ### Test HTML Page Loading Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/testing.md Verifies that core HTML pages of the application load correctly by making GET requests to their respective routes. This includes the home page, poll page, admin page, and embed page, checking for a 200 OK status. ```typescript // Test Home page loads let res = await fetch("/"); expect(res.status).toBe(200); let html = await res.text(); expect(html).toContain("Create a Poll"); // Test Poll page loads (assuming a valid share_id exists) // res = await fetch("/poll/valid_share_id"); // expect(res.status).toBe(200); // Test Admin page loads (assuming a valid admin_id exists) // res = await fetch("/admin/valid_admin_id"); // expect(res.status).toBe(200); // Test Embed page loads (assuming a valid share_id exists) // res = await fetch("/embed/valid_share_id"); // expect(res.status).toBe(200); ``` -------------------------------- ### Create Poll Request (Bash) Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/api.md Example using curl to send a POST request to create a new poll. It includes the poll question, options, and optional settings like multiple selections and expiration time. ```bash curl -X POST http://localhost:3000/api/polls \ -H "Content-Type: application/json" \ -d '{ "question": "Favourite language?", "options": ["TypeScript", "Rust", "Go"], "allow_multiple": false, "expires_in_minutes": 60 # Optional: "starts_at": "2026-03-01T09:00:00Z" }' ``` -------------------------------- ### Server Health Response Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/getting-started.md Example JSON response from the /health endpoint, indicating the server's operational status, uptime, number of polls, and database connectivity. ```json { "status": "ok", "uptime_seconds": 12345, "polls": 42, "database": "ok" } ``` -------------------------------- ### GET /api/polls/admin/:adminId/summary - Results Summary Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/testing.md Provides a plain text summary of the poll results, including the question, options, and vote counts. Returns 404 if the admin ID is not found. ```APIDOC ## GET /api/polls/admin/:adminId/summary ### Description Returns a plain text summary of the poll results, including the question, options, and vote counts. ### Method GET ### Endpoint /api/polls/admin/:adminId/summary ### Parameters #### Path Parameters - **adminId** (string) - Required - The UUID of the poll administrator. ### Response #### Success Response (200) - **Content-Type**: `text/plain` - The response body contains a human-readable summary of the poll results. #### Response Example ```text Poll: Favourite colour? Options: - Red: 10 votes - Blue: 5 votes - Green: 8 votes Total Votes: 23 ``` #### Error Response (404) - **error** (string) - "Poll not found." ``` -------------------------------- ### Get Poll Results Summary Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Fetches a plain-text summary of poll results, suitable for quick sharing via chat or email. The response includes the poll question and a breakdown of each option with its vote count and percentage, followed by the total votes. ```bash curl http://localhost:3000/api/polls/admin/550e8400-e29b-41d4-a716-446655440000/summary ``` -------------------------------- ### Test Poll Results Summary API Endpoint Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/testing.md Tests the plain text summary endpoint GET /api/polls/admin/:adminId/summary. It verifies that the response has Content-Type text/plain and contains a human-readable summary of the poll, including the question, options, and vote counts. ```typescript // Assuming an admin with admin_id 'test_admin_id' has a poll with results const response = await fetch("/api/polls/admin/test_admin_id/summary"); expect(response.headers.get("Content-Type")).toBe("text/plain"); const summaryText = await response.text(); expect(summaryText).toContain("Favourite colour?"); expect(summaryText).toContain("Red: 0 votes"); // Example data // Test unknown admin_id await expect(fetch("/api/polls/admin/unknown_admin_id/summary")).rejects.toThrow("404 Not Found"); ``` -------------------------------- ### Embed a Poll in External Pages using iframe Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Allows embedding a poll into external websites using an iframe element. This provides a compact view of the poll. Examples demonstrate basic embedding and responsive embedding within a container div, including styling options like border-radius and box-shadow. ```html
``` -------------------------------- ### Test Admin Poll Retrieval API Endpoint Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/testing.md Tests the functionality of the GET /api/polls/admin/:adminId endpoint for retrieving full poll data accessible only by the admin. It verifies that the correct poll details including admin and share IDs are returned and handles unknown admin IDs with a 404. ```typescript // Assuming an admin with admin_id 'test_admin_id' exists and has created a poll const pollData = await fetch("/api/polls/admin/test_admin_id").then(res => res.json()); expect(pollData.admin_id).toBe("test_admin_id"); expect(pollData.share_id).toBeDefined(); // Test unknown admin_id await expect(fetch("/api/polls/admin/unknown_admin_id")).rejects.toThrow("404 Not Found"); ``` -------------------------------- ### Bun Web Server with APIs and WebSockets Source: https://github.com/danjdewhurst/bun-poll/blob/main/CLAUDE.md Illustrates setting up a web server using `Bun.serve()`, supporting routing, API endpoints, and WebSocket communication. This replaces frameworks like Express. ```typescript import index from "./index.html" Bun.serve({ routes: { "/": index, "/api/users/:id": { GET: (req) => { return new Response(JSON.stringify({ id: req.params.id })); }, }, }, // optional websocket support websocket: { open: (ws) => { ws.send("Hello, world!"); }, message: (ws, message) => { ws.send(message); }, close: (ws) => { // handle close } }, development: { hmr: true, console: true, } }) ``` -------------------------------- ### Manage Bun Server Instance Reference Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/architecture.md This code illustrates a module-level singleton pattern to manage a Bun server instance reference. It provides functions to set the server instance once it's created and to retrieve it later in route handlers for broadcasting purposes. ```typescript // src/server-ref.ts let serverInstance; export function setServer(s) { serverInstance = s; } export function getServer() { return serverInstance; } ``` -------------------------------- ### Bun.serve() Server Implementation with Routes and WebSocket in TypeScript Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Sets up a Bun server using Bun.serve() to handle HTTP routes for HTML pages and API endpoints, as well as WebSocket connections. It imports HTML content and route handlers, defining a port and various request handlers. Dependencies include HTML files and specific route modules. ```typescript import home from "./frontend/home.html"; import poll from "./frontend/poll.html"; import admin from "./frontend/admin.html"; import embed from "./frontend/embed.html"; import { createPoll, getPoll, votePoll, getAdminPoll } from "./src/routes/polls.ts"; import { healthCheck } from "./src/routes/health.ts"; import { websocketHandlers } from "./src/routes/websocket.ts"; import { setServer } from "./src/server-ref.ts"; const server = Bun.serve({ port: parseInt(process.env.PORT ?? "3000", 10), // Named routes for HTML pages and API endpoints routes: { "/": home, "/poll/:shareId": poll, "/embed/:shareId": embed, "/admin/:adminId": admin, "/health": { GET: healthCheck }, "/api/polls": { POST: createPoll }, "/api/polls/:shareId": { GET: getPoll }, "/api/polls/:shareId/vote": { POST: votePoll }, "/api/polls/admin/:adminId": { GET: getAdminPoll }, }, // Fallback handler for WebSocket upgrades fetch(req, server) { const url = new URL(req.url); const wsMatch = url.pathname.match(/^\/ws\/([a-f0-9]+)$/); if (wsMatch) { const upgraded = server.upgrade(req, { data: { shareId: wsMatch[1] } }); if (upgraded) return undefined; return new Response("WebSocket upgrade failed", { status: 400 }); } return new Response("Not found", { status: 404 }); }, // WebSocket lifecycle handlers websocket: websocketHandlers, }); setServer(server); console.log(`bun-poll running on http://localhost:${server.port}`); ``` -------------------------------- ### Bun Frontend Development with HTML Imports Source: https://github.com/danjdewhurst/bun-poll/blob/main/CLAUDE.md Shows how to use HTML imports for frontend development with Bun, enabling direct import of .tsx, .jsx, or .js files and automatic transpilation and bundling. CSS files can also be imported directly. ```html

Hello, world!

``` -------------------------------- ### GET /api/polls/admin/:adminId Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/api.md Retrieves the full poll data, including the admin ID, for administrative purposes. ```APIDOC ## GET /api/polls/admin/:adminId ### Description Retrieves the full poll data, including the admin ID, for administrative purposes. ### Method GET ### Endpoint /api/polls/admin/:adminId ### Parameters #### Path Parameters - **adminId** (string) - Required - The unique admin ID of the poll. ### Response #### Success Response (200) - **poll** (object) - Contains full poll details including `admin_id`. - **options** (array) - An array of option objects. - **total_votes** (number) - The total number of votes cast for the poll. #### Response Example ```json { "poll": { "id": 1, "share_id": "a1b2c3d4", "admin_id": "550e8400-e29b-41d4-a716-446655440000", "question": "Favourite language?", "allow_multiple": 0, "starts_at": null, "expires_at": null, "created_at": 1700000000000 }, "options": [ { "id": 1, "poll_id": 1, "text": "TypeScript", "position": 0, "votes": 4 }, { "id": 2, "poll_id": 1, "text": "Rust", "position": 1, "votes": 1 }, { "id": 3, "poll_id": 1, "text": "Go", "position": 2, "votes": 0 } ], "total_votes": 5 } ``` ### Errors - `404` - Poll not found ``` -------------------------------- ### Running Bun Server Command Source: https://github.com/danjdewhurst/bun-poll/blob/main/CLAUDE.md Command to run the Bun server with hot module replacement and console logging enabled. This is a simple command-line execution. ```sh bun --hot ./index.ts ``` -------------------------------- ### Running Tests with Bun CLI Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Provides commands to execute tests within the Bun project. It covers running all tests, generating test coverage reports, and targeting specific test files for execution. This is essential for verifying the project's functionality. ```bash # Run all tests bun test # Run tests with coverage bun test --coverage # Run specific test file bun test index.test.ts ``` -------------------------------- ### GET /health Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/api.md Performs a health check on the server, returning its status, uptime, the number of polls, and database connectivity information. ```APIDOC ## GET /health ### Description Returns server status, uptime, poll count, and database connectivity. ### Method GET ### Endpoint `/health` ### Response #### Success Response (200) - **status** (string) - Server status, typically "ok". - **uptime_seconds** (integer) - Server uptime in seconds. - **polls** (integer) - The current number of polls. - **database** (string) - Database connection status, typically "ok". #### Response Example (OK) ```json { "status": "ok", "uptime_seconds": 12345, "polls": 42, "database": "ok" } ``` #### Degraded Response (503) - **status** (string) - Server status, typically "degraded". - **uptime_seconds** (integer) - Server uptime in seconds. - **polls** (null) - Poll count may be null if unavailable. - **database** (string) - Database connection status, typically "error". #### Response Example (Degraded) ```json { "status": "degraded", "uptime_seconds": 12345, "polls": null, "database": "error" } ``` ``` -------------------------------- ### Manage Linting and Formatting with Biome Source: https://github.com/danjdewhurst/bun-poll/blob/main/README.md Provides commands for checking and applying linting and formatting rules using Biome. This ensures code consistency and quality across the project. ```bash # Check for lint and formatting issues bun run lint # Auto-format all files bun run format # Check and auto-fix everything bun run check ``` -------------------------------- ### GET /api/polls/admin/:adminId/export Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/api.md Downloads poll results in CSV or JSON format. The format can be specified using the 'format' query parameter. ```APIDOC ## GET /api/polls/admin/:adminId/export ### Description Downloads poll results in CSV or JSON format. ### Method GET ### Endpoint `/api/polls/admin/:adminId/export` ### Parameters #### Query Parameters - **format** (string) - Optional - `csv` or `json` (default: `json`) ### Response #### Success Response (200) - **CSV Response**: `Content-Type: text/csv`, `Content-Disposition: attachment; filename="poll-.csv"` - **JSON Response**: `Content-Type: application/json`, `Content-Disposition: attachment; filename="poll-.json"` #### Response Example (CSV) ``` Option,Votes,Percentage TypeScript,3,60% Rust,1,20% Go,1,20% ``` #### Response Example (JSON) ```json { "question": "Favourite language?", "options": [ { "text": "TypeScript", "votes": 3, "percentage": "60%" }, { "text": "Rust", "votes": 1, "percentage": "20%" }, { "text": "Go", "votes": 1, "percentage": "20%" } ], "total_votes": 5, "exported_at": "2026-02-27T12:00:00.000Z" } ``` #### Error Response (404) - **Reason**: Poll not found ``` -------------------------------- ### GET /api/polls/:shareId Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/api.md Retrieves details for a specific poll using its share ID. Optionally includes voter token to check voting status. ```APIDOC ## GET /api/polls/:shareId ### Description Retrieves details for a specific poll using its share ID. Optionally includes voter token to check voting status. ### Method GET ### Endpoint /api/polls/:shareId ### Parameters #### Path Parameters - **shareId** (string) - Required - The unique share ID of the poll. #### Query Parameters - **voter_token** (string) - Optional - If provided, `has_voted` reflects whether this token has voted. ### Response #### Success Response (200) - **poll** (object) - Contains poll details including ID, share ID, question, options, and timing. - **options** (array) - An array of option objects, each with ID, poll ID, text, position, and vote count. - **total_votes** (number) - The total number of votes cast for the poll. - **has_voted** (boolean) - Indicates if the provided `voter_token` has already voted. #### Response Example ```json { "poll": { "id": 1, "share_id": "a1b2c3d4", "question": "Favourite language?", "allow_multiple": 0, "starts_at": null, "expires_at": 1700003600000, "created_at": 1700000000000 }, "options": [ { "id": 1, "poll_id": 1, "text": "TypeScript", "position": 0, "votes": 3 }, { "id": 2, "poll_id": 1, "text": "Rust", "position": 1, "votes": 1 }, { "id": 3, "poll_id": 1, "text": "Go", "position": 2, "votes": 0 } ], "total_votes": 4, "has_voted": false } ``` ### Errors - `404` - Poll not found ``` -------------------------------- ### Configure Environment Variables Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/getting-started.md Sets environment variables for the server, such as the port and database file path. Bun automatically loads variables from a `.env` file in the project root. ```env PORT=3000 DB_PATH=bun-poll.sqlite ``` -------------------------------- ### Configure Bun Poll with Environment Variables Source: https://github.com/danjdewhurst/bun-poll/blob/main/README.md Demonstrates how to run the Bun application with specific feature flags disabled using environment variables. This allows for customization of application behavior without modifying the core code. ```bash # Example: run with exports and admin management disabled FEATURE_EXPORTS=false FEATURE_ADMIN_MANAGEMENT=false bun --hot index.ts ``` -------------------------------- ### Create a Poll Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Creates a new poll with a question and options. Returns unique identifiers for public sharing and admin access. ```APIDOC ## POST /api/polls ### Description Creates a new poll with a question and options. Returns unique identifiers for public sharing and admin access. ### Method POST ### Endpoint /api/polls ### Parameters #### Request Body - **question** (string) - Required - The question for the poll. - **options** (array of strings) - Required - An array of possible answers for the poll. - **allow_multiple** (boolean) - Optional - Whether multiple options can be selected. - **expires_in_minutes** (integer) - Optional - The poll will expire after this many minutes. - **starts_at** (string) - Optional - The poll will start at this ISO 8601 timestamp. ### Request Example ```json { "question": "What is your favourite programming language?", "options": ["TypeScript", "Rust", "Go", "Python"], "allow_multiple": false, "expires_in_minutes": 1440 } ``` ### Response #### Success Response (200) - **share_id** (string) - A unique ID for sharing the poll publicly. - **admin_id** (string) - A unique ID for administrative access to the poll. #### Response Example ```json { "share_id": "a1b2c3d4e5f6g7h8", "admin_id": "550e8400-e29b-41d4-a716-446655440000" } ``` ``` -------------------------------- ### Vote on Poll Request (JSON) Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/api.md Example JSON request body for voting on a poll. It requires an array of selected option IDs and a unique voter token for identification and deduplication. ```json { "option_ids": [1], "voter_token": "a1b2c3d4-e5f6-7890-1234-567890abcdef" } ``` -------------------------------- ### GET /embed/:shareId Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/api.md Serves a compact, standalone HTML page designed for iframe embedding. This page displays the poll question, options, and live results with minimal UI. ```APIDOC ## GET /embed/:shareId ### Description Serves a compact, standalone HTML page designed for ` ``` ### Note This is an HTML route and returns an HTML page, not JSON. ``` -------------------------------- ### WebSocket API - Connect to Live Results Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Establishes a WebSocket connection to receive real-time updates for poll results and viewer counts. ```APIDOC ## WebSocket /ws/{pollId} ### Description Connects to a WebSocket channel to receive live updates on poll results, viewer counts, and poll closure events. ### Method WebSocket ### Endpoint `/ws/{pollId}` ### Parameters #### Path Parameters - **pollId** (string) - Required - The unique identifier of the poll to connect to. ### Message Types - **results**: Contains updated poll options and total votes. - **viewers**: Contains the current number of viewers. - **closed**: Indicates the poll has been closed by an admin, includes final results. ### Event Handlers - **onopen**: Called when the connection is established. - **onmessage**: Called when a message is received from the server. - **onerror**: Called when an error occurs. - **onclose**: Called when the connection is closed. ### Request Example ```javascript const ws = new WebSocket('ws://localhost:3000/ws/a1b2c3d4e5f6g7h8'); ws.onopen = () => { console.log('Connected to poll'); }; ws.onmessage = (event) => { const message = JSON.parse(event.data); if (message.type === 'results') { console.log('Updated results:', message.options); console.log('Total votes:', message.total_votes); } if (message.type === 'viewers') { console.log('Current viewers:', message.count); } if (message.type === 'closed') { console.log('Poll closed. Final results:', message.options); } }; ws.onerror = (error) => { console.error('WebSocket error:', error); }; ws.onclose = (event) => { if (event.code === 4004) { console.log('Poll not found'); } }; ``` ``` -------------------------------- ### Check Server Health Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/getting-started.md Retrieves the server's health status via a GET request to the /health endpoint. The response is in JSON format and includes uptime and database status. ```bash curl http://localhost:3000/health ``` -------------------------------- ### Project Structure of bun-poll Source: https://github.com/danjdewhurst/bun-poll/blob/main/README.md This outlines the directory and file structure of the bun-poll project. It highlights the main entry point, source files for database interactions, types, routing, frontend components, and tests. ```tree index.ts Entry point — Bun.serve() with routes & WebSockets src/ db.ts SQLite schema, migrations, prepared statements types.ts Shared TypeScript interfaces server-ref.ts Module-level server reference for WS broadcasting routes/ polls.ts API route handlers (create, get, vote, admin) websocket.ts WebSocket open/close/message handlers frontend/ home.html / home.js Poll creation page poll.html / poll.js Voting & live results page admin.html / admin.js Admin results & share link page embed.html / embed.js / embed.css Compact embeddable poll view styles.css Shared styles index.test.ts Integration tests ``` -------------------------------- ### Configure bun-poll Environment Variables Source: https://context7.com/danjdewhurst/bun-poll/llms.txt Details on configuring the bun-poll server using a .env file. Bun automatically loads environment variables from this file, allowing customization of the port, database path, and feature flags. ```env PORT=3000 DB_PATH=bun-poll.sqlite FEATURE_EXPORTS=true FEATURE_WEBSOCKET=true FEATURE_ADMIN_MANAGEMENT=true ``` -------------------------------- ### GET /api/polls/admin/:adminId/export - Results Export Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/testing.md Exports poll results in either CSV or JSON format. Allows specifying the format via a query parameter. Returns 404 if the admin ID is not found. ```APIDOC ## GET /api/polls/admin/:adminId/export ### Description Exports the results of a poll. The format can be specified as CSV or JSON using the `format` query parameter. Defaults to JSON if not specified. ### Method GET ### Endpoint /api/polls/admin/:adminId/export ### Parameters #### Path Parameters - **adminId** (string) - Required - The UUID of the poll administrator. #### Query Parameters - **format** (string) - Optional - The desired export format (`csv` or `json`). Defaults to `json`. ### Response #### Success Response (200) - **Content-Type**: `text/csv` for CSV format, `application/json` for JSON format. - The response body contains the poll results in the specified format. #### Response Example (CSV) ```csv Question,Option,Votes Favourite colour?,Red,10 Favourite colour?,Blue,5 Favourite colour?,Green,8 ``` #### Response Example (JSON) ```json { "question": "Favourite colour?", "options": [ { "text": "Red", "votes": 10 }, { "text": "Blue", "votes": 5 }, { "text": "Green", "votes": 8 } ], "total_votes": 23, "exported_at": "2023-10-27T10:00:00Z" } ``` #### Error Response (404) - **error** (string) - "Poll not found." ``` -------------------------------- ### Broadcast Poll Updates with Bun Server Publish Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/architecture.md This snippet demonstrates how to broadcast updated poll results to connected clients using Bun's server publish functionality. It ensures real-time updates without manual fan-out or polling. The message is stringified before publishing. ```typescript server.publish(`poll-${shareId}`, JSON.stringify(message)); ``` -------------------------------- ### Get Poll Details (Admin) Response (JSON) Source: https://github.com/danjdewhurst/bun-poll/blob/main/docs/api.md The JSON response when retrieving poll details using the admin ID. This response includes the `admin_id` and all other poll data, unlike the public view. ```json { "poll": { "id": 1, "share_id": "a1b2c3d4", "admin_id": "550e8400-e29b-41d4-a716-446655440000", "question": "Favourite language?", "allow_multiple": 0, "starts_at": null, "expires_at": null, "created_at": 1700000000000 }, "options": [...], "total_votes": 5 } ```