From 1ffac486e5b68ec189aa6184e49d96cda1eaccf0 Mon Sep 17 00:00:00 2001 From: Aidan McAlister Date: Mon, 21 Jul 2025 16:00:11 -0400 Subject: [PATCH 1/3] feat: error page --- claim-db-worker/public/hero-background.svg | 51 ++++++ claim-db-worker/src/index.ts | 54 ++++-- .../src/templates/error-template.ts | 171 +++++++++++------- claim-db-worker/worker-configuration.d.ts | 5 +- claim-db-worker/wrangler.jsonc | 6 +- create-db-worker/package-lock.json | 4 +- 6 files changed, 202 insertions(+), 89 deletions(-) create mode 100644 claim-db-worker/public/hero-background.svg diff --git a/claim-db-worker/public/hero-background.svg b/claim-db-worker/public/hero-background.svg new file mode 100644 index 0000000..45f41f2 --- /dev/null +++ b/claim-db-worker/public/hero-background.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/claim-db-worker/src/index.ts b/claim-db-worker/src/index.ts index d38aaf8..c09c364 100644 --- a/claim-db-worker/src/index.ts +++ b/claim-db-worker/src/index.ts @@ -18,23 +18,23 @@ function generateState(): string { } function errorResponse(title: string, message: string, details?: string, status = 400): Response { - return new Response(getErrorHtml(title, message, details), { + return new Response(getErrorHtml(title, message, details), { status, - headers: { 'Content-Type': 'text/html' } + headers: { 'Content-Type': 'text/html' }, }); } export default { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise { // --- Rate limiting --- - const { success } = await env.CLAIM_DB_RATE_LIMITER.limit({ key: request.url }) + const { success } = await env.CLAIM_DB_RATE_LIMITER.limit({ key: request.url }); if (!success) { - return errorResponse('Rate Limit Exceeded', 'We\'re experiencing high demand. Please try again later.', '', 429); + return errorResponse('Rate Limit Exceeded', "We're experiencing high demand. Please try again later.", '', 429); } const url = new URL(request.url); - + // --- OAuth Callback Handler --- if (url.pathname === '/auth/callback') { const code = url.searchParams.get('code'); @@ -42,7 +42,12 @@ export default { const projectID = url.searchParams.get('projectID'); if (!state) return errorResponse('OAuth Error', 'Missing state parameter.', 'Please try again.'); - if (!projectID) return errorResponse('OAuth Error', 'Missing project ID parameter.', 'Please ensure you are accessing this page with a valid project ID.'); + if (!projectID) + return errorResponse( + 'OAuth Error', + 'Missing project ID parameter.', + 'Please ensure you are accessing this page with a valid project ID.', + ); // Exchange code for access token const tokenResponse = await fetch('https://auth.prisma.io/token', { @@ -51,7 +56,7 @@ export default { body: new URLSearchParams({ grant_type: 'authorization_code', code: code!, - redirect_uri: new URL("/auth/callback", request.url).toString(), + redirect_uri: new URL('/auth/callback', request.url).toString(), client_id: env.CLIENT_ID, client_secret: env.CLIENT_SECRET, }).toString(), @@ -59,7 +64,12 @@ export default { if (!tokenResponse.ok) { const text = await tokenResponse.text(); - return errorResponse('OAuth Error', 'Failed to authenticate with Prisma. Please try again.', `Status: ${tokenResponse.status}\nResponse: ${text}`, 500); + return errorResponse( + 'OAuth Error', + 'Failed to authenticate with Prisma. Please try again.', + `Status: ${tokenResponse.status}\nResponse: ${text}`, + 500, + ); } const tokenData = (await tokenResponse.json()) as { access_token: string }; @@ -76,26 +86,30 @@ export default { if (transferResponse.ok) { env.CREATE_DB_DATASET.writeDataPoint({ - blobs: ["database_claimed"], - indexes: ["claim_db"] + blobs: ['database_claimed'], + indexes: ['claim_db'], }); - - return new Response(getClaimSuccessHtml(projectID), { - headers: { 'Content-Type': 'text/html' } + + return new Response(getClaimSuccessHtml(projectID), { + headers: { 'Content-Type': 'text/html' }, }); } else { const responseText = await transferResponse.text(); - return errorResponse('Project Transfer Failed', 'Failed to transfer the project. Please try again.', `Status: ${transferResponse.status}\nResponse: ${responseText}`, 500); + return errorResponse( + 'Project Transfer Failed', + 'Failed to transfer the project. Please try again.', + `Status: ${transferResponse.status}\nResponse: ${responseText}`, + 500, + ); } } // --- Main Claim Page Handler --- const projectID = url.searchParams.get('projectID'); if (projectID) { - - const redirectUri = new URL("/auth/callback", request.url); + const redirectUri = new URL('/auth/callback', request.url); redirectUri.searchParams.set('projectID', projectID); - + const authParams = new URLSearchParams({ client_id: env.CLIENT_ID, redirect_uri: redirectUri.toString(), @@ -110,6 +124,10 @@ export default { } // --- Fallback: No project ID provided --- - return errorResponse('Missing Project ID', 'No project ID was provided in the request.', 'Please ensure you are accessing this page with a valid project ID parameter.'); + return errorResponse( + 'Missing Project ID', + 'No project ID was provided in the request.', + 'Please ensure you are accessing this page with a valid project ID parameter.', + ); }, }; diff --git a/claim-db-worker/src/templates/error-template.ts b/claim-db-worker/src/templates/error-template.ts index 6f80113..417f933 100644 --- a/claim-db-worker/src/templates/error-template.ts +++ b/claim-db-worker/src/templates/error-template.ts @@ -1,68 +1,109 @@ export function getErrorHtml(title: string, message: string, details?: string) { return ` - - - - - ${title} - - - -
-

❌ ${title}

-

${message}

- ${details ? `
${details}
` : ''} + + + + + ${title} + + + +
+
+ + + + ${title}
- - - `; -} \ No newline at end of file +
${message}
+ ${ + details + ? ` +
${details}
+ ` + : '' + } +
+ + + + `; +} diff --git a/claim-db-worker/worker-configuration.d.ts b/claim-db-worker/worker-configuration.d.ts index 34f12a1..b614076 100644 --- a/claim-db-worker/worker-configuration.d.ts +++ b/claim-db-worker/worker-configuration.d.ts @@ -1,13 +1,12 @@ /* eslint-disable */ -// Generated by Wrangler by running `wrangler types` (hash: f1ff04827a5b267b343805d7909ab04e) +// Generated by Wrangler by running `wrangler types` (hash: b19bb9f3c86ff56bcefeed01df89af09) // Runtime types generated with workerd@1.20250617.0 2025-06-28 declare namespace Cloudflare { interface Env { CLAIM_DB_RATE_LIMIT_KV: KVNamespace; - INTEGRATION_TOKEN: string; - CLIENT_SECRET: string; CREATE_DB_DATASET: AnalyticsEngineDataset; CLAIM_DB_RATE_LIMITER: RateLimit; + ASSETS: Fetcher; } } interface Env extends Cloudflare.Env {} diff --git a/claim-db-worker/wrangler.jsonc b/claim-db-worker/wrangler.jsonc index 12b3d6c..b42e233 100644 --- a/claim-db-worker/wrangler.jsonc +++ b/claim-db-worker/wrangler.jsonc @@ -14,6 +14,10 @@ "dataset": "create_db_dataset", }, ], + "assets": { + "directory": "./public", + "binding": "ASSETS", + }, "unsafe": { "bindings": [ { @@ -21,7 +25,7 @@ "type": "ratelimit", "namespace_id": "1006", "simple": { - "limit": 1, + "limit": 100, "period": 60, }, }, diff --git a/create-db-worker/package-lock.json b/create-db-worker/package-lock.json index b78324e..a0d74cf 100644 --- a/create-db-worker/package-lock.json +++ b/create-db-worker/package-lock.json @@ -1,11 +1,11 @@ { - "name": "worker", + "name": "create-db-worker", "version": "0.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "worker", + "name": "create-db-worker", "version": "0.0.2", "devDependencies": { "@cloudflare/vitest-pool-workers": "^0.8.19", From 1d74dd9681bbce585b2c71b5b7fa79109f97826c Mon Sep 17 00:00:00 2001 From: Aidan McAlister Date: Mon, 21 Jul 2025 17:05:34 -0400 Subject: [PATCH 2/3] feat: remaining styles applied --- claim-db-worker/public/arrow-right.svg | 3 + claim-db-worker/public/arrow-up.svg | 3 + claim-db-worker/public/db-icon.svg | 3 + claim-db-worker/public/db-img.svg | 99 ++++++++++++ .../public/prisma-postgres-logo.svg | 4 + claim-db-worker/src/index.ts | 7 + .../src/templates/claim-success-template.ts | 148 +++++++++++++++--- .../src/templates/claim-template.ts | 99 +++++++++--- .../src/templates/error-template.ts | 29 ++-- 9 files changed, 333 insertions(+), 62 deletions(-) create mode 100644 claim-db-worker/public/arrow-right.svg create mode 100644 claim-db-worker/public/arrow-up.svg create mode 100644 claim-db-worker/public/db-icon.svg create mode 100644 claim-db-worker/public/db-img.svg create mode 100644 claim-db-worker/public/prisma-postgres-logo.svg diff --git a/claim-db-worker/public/arrow-right.svg b/claim-db-worker/public/arrow-right.svg new file mode 100644 index 0000000..cf6f781 --- /dev/null +++ b/claim-db-worker/public/arrow-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/claim-db-worker/public/arrow-up.svg b/claim-db-worker/public/arrow-up.svg new file mode 100644 index 0000000..73746a8 --- /dev/null +++ b/claim-db-worker/public/arrow-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/claim-db-worker/public/db-icon.svg b/claim-db-worker/public/db-icon.svg new file mode 100644 index 0000000..17844c4 --- /dev/null +++ b/claim-db-worker/public/db-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/claim-db-worker/public/db-img.svg b/claim-db-worker/public/db-img.svg new file mode 100644 index 0000000..c9d7869 --- /dev/null +++ b/claim-db-worker/public/db-img.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/claim-db-worker/public/prisma-postgres-logo.svg b/claim-db-worker/public/prisma-postgres-logo.svg new file mode 100644 index 0000000..27527b4 --- /dev/null +++ b/claim-db-worker/public/prisma-postgres-logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/claim-db-worker/src/index.ts b/claim-db-worker/src/index.ts index c09c364..ad8a1e0 100644 --- a/claim-db-worker/src/index.ts +++ b/claim-db-worker/src/index.ts @@ -35,6 +35,13 @@ export default { const url = new URL(request.url); + // Add a test route for local development to preview the success page + if (url.pathname === '/test-success') { + return new Response(getClaimSuccessHtml('cmddkid4303fly70vbmzqekl9'), { + headers: { 'Content-Type': 'text/html' }, + }); + } + // --- OAuth Callback Handler --- if (url.pathname === '/auth/callback') { const code = url.searchParams.get('code'); diff --git a/claim-db-worker/src/templates/claim-success-template.ts b/claim-db-worker/src/templates/claim-success-template.ts index 471c142..dcfbe7a 100644 --- a/claim-db-worker/src/templates/claim-success-template.ts +++ b/claim-db-worker/src/templates/claim-success-template.ts @@ -1,22 +1,134 @@ export function getClaimSuccessHtml(projectID: string) { return ` - - - - - Project Claimed! - - - -
-

🎉 Congratulations!

-

You have successfully claimed the database.

-
- - + + + + + + Congratulations! + + + +
+ +
Congratulations!
+
You have successfully claimed your database
+ + Go use your database + Arrow up + +
+ Database Success + + + +
+
+ + `; } diff --git a/claim-db-worker/src/templates/claim-template.ts b/claim-db-worker/src/templates/claim-template.ts index d1cf074..8ce1afe 100644 --- a/claim-db-worker/src/templates/claim-template.ts +++ b/claim-db-worker/src/templates/claim-template.ts @@ -7,54 +7,101 @@ export function getClaimHtml(projectID: string, authUrl: string) { Claim Project +