From 2a563bbd7a118bdb9aded388420a3992c1c8c893 Mon Sep 17 00:00:00 2001 From: John Costa Date: Mon, 10 Nov 2025 21:23:09 +0000 Subject: [PATCH] signing petition through fetch request instead of direct db connection --- bun.lock | 20 ++++++++++-- packages/backend/package.json | 3 +- packages/backend/src/routes/sign-petition.ts | 15 ++++----- packages/frontend/package.json | 3 +- packages/frontend/src/network/index.ts | 15 +++++++++ packages/frontend/src/state/index.ts | 0 packages/types/.gitignore | 34 ++++++++++++++++++++ packages/types/index.ts | 11 +++++++ packages/types/package.json | 15 +++++++++ packages/types/tsconfig.json | 29 +++++++++++++++++ 10 files changed, 131 insertions(+), 14 deletions(-) create mode 100644 packages/frontend/src/network/index.ts create mode 100644 packages/frontend/src/state/index.ts create mode 100644 packages/types/.gitignore create mode 100644 packages/types/index.ts create mode 100644 packages/types/package.json create mode 100644 packages/types/tsconfig.json diff --git a/bun.lock b/bun.lock index 839637b..faacd2f 100644 --- a/bun.lock +++ b/bun.lock @@ -10,6 +10,7 @@ "dotenv": "^17.2.3", "drizzle-orm": "^0.44.7", "pg": "^8.16.3", + "types": "workspace:*", "zod": "^4.1.12", }, "devDependencies": { @@ -74,8 +75,9 @@ "sonner": "^1.7.4", "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", + "types": "workspace:types", "vaul": "^0.9.9", - "zod": "^3.25.76", + "zod": "^4.1.12", }, "devDependencies": { "@eslint/js": "^9.32.0", @@ -97,6 +99,18 @@ "vite": "^5.4.19", }, }, + "packages/types": { + "name": "types", + "dependencies": { + "zod": "^4.1.12", + }, + "devDependencies": { + "@types/bun": "latest", + }, + "peerDependencies": { + "typescript": "^5", + }, + }, }, "packages": { "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], @@ -957,6 +971,8 @@ "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + "types": ["types@workspace:packages/types"], + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], "typescript-eslint": ["typescript-eslint@8.46.3", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.46.3", "@typescript-eslint/parser": "8.46.3", "@typescript-eslint/typescript-estree": "8.46.3", "@typescript-eslint/utils": "8.46.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-bAfgMavTuGo+8n6/QQDVQz4tZ4f7Soqg53RbrlZQEoAltYop/XR4RAts/I0BrO3TTClTSTFJ0wYbla+P8cEWJA=="], @@ -1059,8 +1075,6 @@ "tailwindcss/postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], - "victoria-way-carpark/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "vite/esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="], "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], diff --git a/packages/backend/package.json b/packages/backend/package.json index a9e17ca..00cfb49 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -16,6 +16,7 @@ "dotenv": "^17.2.3", "drizzle-orm": "^0.44.7", "pg": "^8.16.3", - "zod": "^4.1.12" + "zod": "^4.1.12", + "types": "workspace:*" } } diff --git a/packages/backend/src/routes/sign-petition.ts b/packages/backend/src/routes/sign-petition.ts index d5f50f2..9562157 100644 --- a/packages/backend/src/routes/sign-petition.ts +++ b/packages/backend/src/routes/sign-petition.ts @@ -1,11 +1,6 @@ -import { z } from "zod" +import type 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(), -}) +import { signedPetitionSchema, signPetitionSchema } from 'types' export const signPetition = async (req: Request): Promise => { const body = await req.json() @@ -15,15 +10,17 @@ export const signPetition = async (req: Request): Promise => { return Response.json({ error: validatedBody.error }, { status: 400 }); } - const insertedSignature = await insertSignature({ + const _insertedSignature = await insertSignature({ email: validatedBody.data.email, name: validatedBody.data.name, comment: validatedBody.data.comment, }) - if (!insertedSignature) { + if (!_insertedSignature) { return Response.json({ error: "inserting signature in database" }, { status: 500 }); } + const insertedSignature = _insertedSignature satisfies z.infer + return Response.json(insertedSignature, { status: 200 }); } diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 3e0f172..865912e 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -60,7 +60,8 @@ "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", "vaul": "^0.9.9", - "zod": "^3.25.76" + "zod": "^4.1.12", + "types": "workspace:types" }, "devDependencies": { "@eslint/js": "^9.32.0", diff --git a/packages/frontend/src/network/index.ts b/packages/frontend/src/network/index.ts new file mode 100644 index 0000000..68b2a71 --- /dev/null +++ b/packages/frontend/src/network/index.ts @@ -0,0 +1,15 @@ +import { z } from "zod"; +import { signedPetitionSchema, signPetitionSchema } from 'types'; + +const baseURL = import.meta.env.BASE_URL; + +export const signSignature = async (signature: z.infer): Promise> => { + const res = await fetch(baseURL, { + method: 'POST', body: JSON.stringify(signature), + }) + + const body = await res.json(); + const validatedBody = signedPetitionSchema.parse(body); + + return validatedBody +} diff --git a/packages/frontend/src/state/index.ts b/packages/frontend/src/state/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/types/.gitignore b/packages/types/.gitignore new file mode 100644 index 0000000..a14702c --- /dev/null +++ b/packages/types/.gitignore @@ -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 diff --git a/packages/types/index.ts b/packages/types/index.ts new file mode 100644 index 0000000..d766460 --- /dev/null +++ b/packages/types/index.ts @@ -0,0 +1,11 @@ +import z from "zod"; + +export const signPetitionSchema = z.object({ + email: z.string(), + name: z.string().trim().min(1).max(30).nullable(), + comment: z.string().trim().min(10).max(10_000).nullable(), +}) + +export const signedPetitionSchema = signPetitionSchema.extend({ + id: z.uuid(), +}) diff --git a/packages/types/package.json b/packages/types/package.json new file mode 100644 index 0000000..c89c898 --- /dev/null +++ b/packages/types/package.json @@ -0,0 +1,15 @@ +{ + "name": "types", + "module": "index.ts", + "type": "module", + "private": true, + "devDependencies": { + "@types/bun": "latest" + }, + "peerDependencies": { + "typescript": "^5" + }, + "dependencies": { + "zod": "^4.1.12" + } +} diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json new file mode 100644 index 0000000..bfa0fea --- /dev/null +++ b/packages/types/tsconfig.json @@ -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 + } +}