inserting signature endpoint and database methods

This commit is contained in:
John Costa
2025-11-07 17:53:46 +01:00
parent 13414f95cc
commit 42e4abf438
9 changed files with 280 additions and 1 deletions

34
packages/backend/.gitignore vendored Normal file
View File

@@ -0,0 +1,34 @@
# dependencies (bun install)
node_modules
# output
out
dist
*.tgz
# code coverage
coverage
*.lcov
# logs
logs
_.log
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# caches
.eslintcache
.cache
*.tsbuildinfo
# IntelliJ based IDEs
.idea
# Finder (MacOS) folder config
.DS_Store

View File

@@ -0,0 +1,11 @@
import 'dotenv/config';
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
out: './drizzle',
schema: './src/models/schema.ts',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL!,
},
});

View File

@@ -0,0 +1,21 @@
{
"name": "backend",
"module": "index.ts",
"type": "module",
"private": true,
"devDependencies": {
"@types/bun": "latest",
"@types/pg": "^8.15.6",
"drizzle-kit": "^0.31.6",
"tsx": "^4.20.6"
},
"peerDependencies": {
"typescript": "^5"
},
"dependencies": {
"dotenv": "^17.2.3",
"drizzle-orm": "^0.44.7",
"pg": "^8.16.3",
"zod": "^4.1.12"
}
}

View File

@@ -0,0 +1,11 @@
import 'dotenv/config';
import { drizzle } from 'drizzle-orm/node-postgres';
import { pgTable, text, uuid } from 'drizzle-orm/pg-core';
const DATABASE_URL = process.env.DATABASE_URL;
if (!DATABASE_URL) {
throw new Error("DATABASE_URL is missing")
}
export const db = drizzle(DATABASE_URL);

View File

@@ -0,0 +1,8 @@
import { db } from "./database";
import { signaturesTable } from "./schema";
export const insertSignature = async (signature: typeof signaturesTable.$inferInsert): Promise<typeof signaturesTable.$inferSelect | undefined> => {
const [insertedSignature] = await db.insert(signaturesTable).values(signature).returning();
return insertedSignature;
}

View File

@@ -0,0 +1,8 @@
import { pgTable, text, uuid } from "drizzle-orm/pg-core";
export const signaturesTable = pgTable("signatures", {
id: uuid().primaryKey().defaultRandom(),
email: text().notNull(),
name: text(),
comment: text(),
});

View File

@@ -0,0 +1,29 @@
import { z } from "zod"
import { insertSignature } from "../models";
const signPetitionSchema = z.object({
email: z.string(),
name: z.string().trim().min(1).max(30).optional(),
comment: z.string().trim().min(10).max(10_000).optional(),
})
export const signPetition = async (req: Request): Promise<Response> => {
const body = await req.json()
const validatedBody = signPetitionSchema.safeParse(body);
if (!validatedBody.success) {
return Response.json({ error: validatedBody.error }, { status: 400 });
}
const insertedSignature = await insertSignature({
email: validatedBody.data.email,
name: validatedBody.data.name,
comment: validatedBody.data.comment,
})
if (!insertedSignature) {
return Response.json({ error: "inserting signature in database" }, { status: 500 });
}
return Response.json(insertedSignature, { status: 200 });
}

View File

@@ -0,0 +1,29 @@
{
"compilerOptions": {
// Environment setup & latest features
"lib": ["ESNext"],
"target": "ESNext",
"module": "Preserve",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}