From 64759ce17d329d50ef8365944c854ffa8aa72de7 Mon Sep 17 00:00:00 2001 From: Web Date: Mon, 14 Sep 2026 13:23:14 +0000 Subject: [PATCH] founders card --- .gitignore | 1 + KK_cardgen_INTEGRATION.md | 205 +++ next.config.ts | 4 +- package-lock.json | 825 ++++++++++++ package.json | 5 +- public/fonts/Inter-Bold.ttf | Bin 0 -> 67556 bytes public/fonts/Inter-Regular.ttf | Bin 0 -> 67336 bytes public/fonts/Montserrat-Bold.ttf | Bin 0 -> 48824 bytes public/fonts/Montserrat-Regular.ttf | Bin 0 -> 48832 bytes public/fonts/Oswald-Bold.ttf | Bin 0 -> 26900 bytes public/fonts/Oswald-Regular.ttf | Bin 0 -> 26864 bytes public/fonts/PlayfairDisplay-Bold.ttf | Bin 0 -> 54060 bytes public/fonts/PlayfairDisplay-Regular.ttf | Bin 0 -> 54020 bytes public/fonts/Roboto-Bold.ttf | Bin 0 -> 42708 bytes public/fonts/Roboto-Regular.ttf | Bin 0 -> 42576 bytes schemas/early_player_emails.md | 13 + src/app/api/download/[jobId]/route.ts | 48 + .../presets/[presetId]/font/route.ts | 46 + .../presets/[presetId]/image/route.ts | 50 + .../founders-card/presets/[presetId]/route.ts | 26 + src/app/api/founders-card/presets/route.ts | 142 +++ src/app/api/founders-card/route.ts | 48 + src/app/api/founders-card/signup/route.ts | 99 ++ src/app/api/founders-card/signups/route.ts | 20 + src/app/api/generate/route.ts | 169 +++ .../early-emails-list.tsx | 159 +++ src/app/founders-card-design/editor.tsx | 1135 +++++++++++++++++ src/app/founders-card-design/page.tsx | 38 + src/app/globals.css | 80 ++ src/app/ledger-book/page.tsx | 8 +- src/app/page.tsx | 21 +- src/app/settings/page.tsx | 8 +- src/components/admin-accounts-editor.tsx | 13 +- src/components/admin-dashboard.tsx | 143 --- src/components/admin-header.tsx | 72 +- src/components/admin-nav-tabs.tsx | 109 ++ src/lib/auth/page-access-labels.ts | 2 + src/lib/auth/permissions.ts | 25 + src/lib/card-gen/cors.ts | 13 + src/lib/card-gen/create-zip.ts | 30 + src/lib/card-gen/draw-id.ts | 118 ++ src/lib/card-gen/early-player-emails.ts | 115 ++ src/lib/card-gen/file-ext.ts | 18 + src/lib/card-gen/font-files.ts | 24 + src/lib/card-gen/fonts.ts | 35 + src/lib/card-gen/generate-pool.ts | 90 ++ src/lib/card-gen/id-config.ts | 295 +++++ src/lib/card-gen/jobs.ts | 71 ++ src/lib/card-gen/local-store.ts | 212 +++ src/lib/card-gen/preset-api.ts | 114 ++ src/lib/card-gen/preset-store.ts | 242 ++++ src/lib/card-gen/progress.ts | 16 + src/lib/card-gen/public-rate-limit.ts | 40 + src/lib/card-gen/render-one.ts | 27 + src/lib/card-gen/render-public.ts | 91 ++ src/types/database.ts | 8 + workers/generate-id.cjs | 128 ++ 57 files changed, 5013 insertions(+), 188 deletions(-) create mode 100644 KK_cardgen_INTEGRATION.md create mode 100644 public/fonts/Inter-Bold.ttf create mode 100644 public/fonts/Inter-Regular.ttf create mode 100644 public/fonts/Montserrat-Bold.ttf create mode 100644 public/fonts/Montserrat-Regular.ttf create mode 100644 public/fonts/Oswald-Bold.ttf create mode 100644 public/fonts/Oswald-Regular.ttf create mode 100644 public/fonts/PlayfairDisplay-Bold.ttf create mode 100644 public/fonts/PlayfairDisplay-Regular.ttf create mode 100644 public/fonts/Roboto-Bold.ttf create mode 100644 public/fonts/Roboto-Regular.ttf create mode 100644 schemas/early_player_emails.md create mode 100644 src/app/api/download/[jobId]/route.ts create mode 100644 src/app/api/founders-card/presets/[presetId]/font/route.ts create mode 100644 src/app/api/founders-card/presets/[presetId]/image/route.ts create mode 100644 src/app/api/founders-card/presets/[presetId]/route.ts create mode 100644 src/app/api/founders-card/presets/route.ts create mode 100644 src/app/api/founders-card/route.ts create mode 100644 src/app/api/founders-card/signup/route.ts create mode 100644 src/app/api/founders-card/signups/route.ts create mode 100644 src/app/api/generate/route.ts create mode 100644 src/app/founders-card-design/early-emails-list.tsx create mode 100644 src/app/founders-card-design/editor.tsx create mode 100644 src/app/founders-card-design/page.tsx create mode 100644 src/components/admin-nav-tabs.tsx create mode 100644 src/lib/card-gen/cors.ts create mode 100644 src/lib/card-gen/create-zip.ts create mode 100644 src/lib/card-gen/draw-id.ts create mode 100644 src/lib/card-gen/early-player-emails.ts create mode 100644 src/lib/card-gen/file-ext.ts create mode 100644 src/lib/card-gen/font-files.ts create mode 100644 src/lib/card-gen/fonts.ts create mode 100644 src/lib/card-gen/generate-pool.ts create mode 100644 src/lib/card-gen/id-config.ts create mode 100644 src/lib/card-gen/jobs.ts create mode 100644 src/lib/card-gen/local-store.ts create mode 100644 src/lib/card-gen/preset-api.ts create mode 100644 src/lib/card-gen/preset-store.ts create mode 100644 src/lib/card-gen/progress.ts create mode 100644 src/lib/card-gen/public-rate-limit.ts create mode 100644 src/lib/card-gen/render-one.ts create mode 100644 src/lib/card-gen/render-public.ts create mode 100644 workers/generate-id.cjs diff --git a/.gitignore b/.gitignore index a3813a4..c57aee7 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,5 @@ next-env.d.ts # admin panel accounts (passwords hashed; still keep private) /data/admin-accounts.json /data/admin-audit.jsonl +/data/founders-card-presets/ /data/*.tmp diff --git a/KK_cardgen_INTEGRATION.md b/KK_cardgen_INTEGRATION.md new file mode 100644 index 0000000..90c2dc4 --- /dev/null +++ b/KK_cardgen_INTEGRATION.md @@ -0,0 +1,205 @@ +# Prompt: add KK Card Gen to this Next.js app + +Implement the **KK Card Gen** feature inside **this** existing Next.js app. Do not create a second Next app. Do not iframe the old app. Merge it as a route + APIs + libs. + +Source of truth if you can read files from disk: `F:\Projects\Node\kk_card_gen` +If you cannot access that folder, reimplement from this spec exactly. + +## Product + +Personal tool to stamp sequential user IDs onto a local base card image and download a zip of PNGs. + +User flow: + +1. Pick a base image (PNG/JPG/WebP, max 10MB) from disk or drop it. +2. Configure ID: prefix, suffix, start number, pad length 0–6, count 1–1000 (default 1000). +3. Style text: preset font or uploaded TTF/OTF, size, color, bold, italic, left/center/right. +4. Optional drop shadow: color, opacity, blur, offset X/Y. +5. Optional outline: color, opacity, width. +6. Position: drag the sample ID on the preview, click to place, or nudge X/Y %. +7. Click Generate. Server generates PNGs in parallel, then zips them. +8. UI shows live progress: `Generating 12 / 1000` then `Zipping 12 / 1000`. +9. When done, show a **Download ids.zip** link. Do **not** fetch the zip as a blob in JS and auto-download. That hung on the server. +10. Filenames = sanitized ID + `.png` (example `KK0001.png`). + +No header/marketing chrome. No helper text like “Drop a card image with an empty ID area…”. Empty preview only needs “Select a base photo”. + +## Hosting constraints (must follow) + +- Route handlers: `export const runtime = "nodejs"` (never Edge). +- Native module `@napi-rs/canvas` + Node `worker_threads`. +- Host must be a real Node server (VPS / `next start`). Vercel-style serverless is a poor fit. +- `maxDuration = 300` on generate. +- Zip files live on disk under `os.tmpdir()/kk-card-jobs//` for 15 minutes so any Node worker on the same machine can serve the download. Do **not** store jobs in an in-memory `Map`. + +## Dependencies + +```bash +npm install @napi-rs/canvas archiver +npm install -D @types/archiver +``` + +`next.config` must include: + +```ts +serverExternalPackages: ["@napi-rs/canvas"] +``` + +Merge with existing config. Do not remove other settings. + +## Files to add + +Adapt `@/` aliases if this repo uses `src/`. Keep the **worker file name and cwd-relative path** unless you update `generate-pool.ts` to match. + +``` +app/cards/page.tsx # or another unused route; render +app/cards/editor.tsx # "use client" editor UI +app/api/generate/route.ts +app/api/download/[jobId]/route.ts +lib/id-config.ts +lib/draw-id.ts +lib/fonts.ts +lib/progress.ts +lib/jobs.ts +lib/create-zip.ts +lib/generate-pool.ts +lib/register-fonts.ts # optional if only workers register fonts +workers/generate-id.cjs # MUST be a real file on disk at repo root +public/fonts/Inter-Regular.ttf +public/fonts/Inter-Bold.ttf +public/fonts/Roboto-Regular.ttf +public/fonts/Roboto-Bold.ttf +public/fonts/Oswald-Regular.ttf +public/fonts/Oswald-Bold.ttf +public/fonts/Montserrat-Regular.ttf +public/fonts/Montserrat-Bold.ttf +public/fonts/PlayfairDisplay-Regular.ttf +public/fonts/PlayfairDisplay-Bold.ttf +``` + +If this app already has `app/page.tsx` you care about, **do not overwrite it**. Put the editor on `/cards` (or `/kk-card-gen`). + +Copy fonts from `F:\Projects\Node\kk_card_gen\public\fonts` if possible. Otherwise download Inter / Roboto / Oswald / Montserrat / Playfair Display regular+bold TTF (latin 400 + 700) into those exact filenames. + +Add matching `@font-face` rules to the app’s global CSS so the **browser preview** uses the same files as the server. Families: `Inter`, `Roboto`, `Oswald`, `Montserrat`, `Playfair Display`. + +## Shared drawing rules (preview MUST match export) + +Both client canvas and worker canvas must use the same logic: + +- Position: `x = xPercent/100 * width`, `y = yPercent/100 * height` +- `textBaseline = "alphabetic"` — **never** `"middle"` (browser vs Skia disagree; export sat too low) +- Measure `actualBoundingBoxAscent/Descent` (fallback `fontSize * 0.8` / `0.2`) +- Alphabetic Y for visual center: `baselineY = y + (ascent - descent) / 2` +- Font string: `` `${italic?} ${bold?700:400} ${fontSize}px "${fontFamily}"` `` +- Outline: `strokeText` first (`lineJoin: "round"`), then clear shadow, then `fillText` +- Shadow via `shadowColor/Blur/OffsetX/OffsetY` (hex + opacity → rgba) +- Font size is pixels at **source image resolution**. Preview canvas internal size = naturalWidth/Height; CSS scales it. Mouse coords: map from `getBoundingClientRect()` to canvas pixels, then to percents. + +ID string: + +```ts +`${prefix}${String(n).padStart(pad, "0")}${suffix}` +``` + +Filename: strip `/ \ : * ? " < > |`, trim, fallback `"id"`. + +Limits: count 1–1000, pad 0–6, start 0–1_000_000, fontSize 8–400, image 10MB, font 5MB, hex colors `#rgb` / `#rrggbb` / `#rrggbbaa`. + +Default config: prefix `KK`, start `1`, pad `4`, count `1000`, font `Inter`, size `48`, color `#111111`, align `center`, position 50/50, shadow/outline off. + +Custom uploaded font family name: `CustomUpload` (FontFace in browser; `GlobalFonts.registerFromPath` in workers). + +## Worker pool (required for speed) + +Do **not** generate 1000 images on the Next.js request thread in a single loop. + +`lib/generate-pool.ts`: + +- Split tasks across `min(cpu, 8, taskCount)` workers +- Spawn with `createRequire(...).("node:worker_threads").Worker` — **do not** `import { Worker } from "node:worker_threads"` then `new Worker(path)`. Turbopack/webpack intercepts `new Worker()` and breaks (`__dirname is not defined` / missing worker module). +- Worker path: `path.join(process.cwd(), "workers", "generate-id.cjs")` +- Each worker gets `{ imagePath, fonts: [{path,family}], style, tasks: [{text,outPath}] }` +- Worker posts `{ type: "progress" }` after each PNG +- Parent aggregates and streams generate progress + +`workers/generate-id.cjs` must be **CommonJS** (`require("@napi-rs/canvas")`). ESM workers broke canvas. Worker: register fonts, `loadImage`, one canvas, draw, `encode("png")`, `writeFile`. + +## Generate API — `POST /api/generate` + +`multipart/form-data`: + +- `image` File +- `font` File (only if custom) +- `config` JSON string of `GenerateConfig` + +Validation errors: JSON `{ error }` with 4xx. + +Success: `Content-Type: application/x-ndjson`, `Cache-Control: no-store`, `X-Accel-Buffering: no`. + +Stream one JSON object per line: + +```json +{"phase":"generate","current":12,"total":1000} +{"phase":"zip","current":12,"total":1000} +{"phase":"done","id":""} +{"phase":"error","message":"..."} +``` + +Pipeline: + +1. `createJobDir()` → `{ id, dir, pngDir, zipPath }` under `tmpdir()/kk-card-jobs//` +2. Write base image to disk; write custom font if any +3. Build file list of `{ text, name, path }` +4. `generatePngsInWorkers` + stream generate events +5. Zip with `archiver` `ZipArchive` (`new ZipArchive({ zlib: { level: 6 } })`). `@types/archiver` has no default factory; import `{ ZipArchive } from "archiver"`. +6. Stream zip progress via archiver `progress` +7. `{"phase":"done","id"}` — zip stays on disk. Do not stream the zip in this response. + +## Download API — `GET /api/download/[jobId]` + +- Validate UUID (prevent path traversal) +- `stat` `ids.zip`; 404 if missing/empty +- Stream file with `Content-Type: application/zip`, `Content-Length`, `Content-Disposition: attachment; filename="ids.zip"` +- Do **not** delete the zip on first download (link should work if they click twice). TTL sweep on new jobs is enough. +- Next 16 params: `const { jobId } = await context.params` + +## Editor UI + +Client component. Two columns: preview left, controls right (base image, user ID, text style, drop shadow, outline, position, progress, download link, generate button). + +Preview: canvas at natural image size, overlay sample ID (`prefix+pad(start)+suffix`), dashed selection box, drag/click-to-place. + +Generate: + +- POST FormData to `/api/generate` +- Read body as NDJSON (buffer split on `\n`) +- Update progress bar + button label (`Generating 12 / 1000`, `Zipping 12 / 1000`) +- On `done`, set `downloadHref = /api/download/${id}` and show `Download ids.zip` +- Never `response.blob()` the zip + +Match existing app look if there is a design system. If the app already has Tailwind, reuse it (dark zinc/indigo is fine). If not, add minimal CSS; do not force a full Tailwind install unless the app already has it. + +Do not add a marketing header. + +## Pitfalls + +1. `textBaseline: "middle"` → generated text sits lower than preview. +2. Auto-download via `fetch` + `blob()` → hangs on server. Use a link. +3. In-memory job map → download 404/hang with multiple Node workers. Use disk + UUID. +4. `new Worker()` imported from `worker_threads` → Next bundles it and breaks. Use `createRequire` + `threads.Worker`. +5. Worker must be `.cjs` on disk at `workers/generate-id.cjs` relative to `process.cwd()` (the Next app root). +6. Preview fonts need `@font-face`; server fonts need TTF files under `public/fonts` with the names in `lib/fonts.ts`. +7. Do not put generate/download on Edge. +8. Archiver v8: `import { ZipArchive } from "archiver"` then `new ZipArchive(...)`. + +## Verify before done + +1. Typecheck / lint the new files. +2. Open the new route in the browser. No leftover header copy. +3. Upload a card, place the ID, generate **12** images. Confirm progress then a working **Download ids.zip** link. Unzip: `KK0001.png` … `KK0012.png`. +4. Confirm preview position matches a generated PNG (not shifted down). +5. Toggle shadow + outline and generate 1 image; both appear. +6. Confirm `/api/generate` is not Edge. + +If `F:\Projects\Node\kk_card_gen` is readable, **copy those files and adapt imports/routes** rather than rewriting from scratch. Preserve worker + draw behavior. diff --git a/next.config.ts b/next.config.ts index cb651cd..80435c2 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,5 +1,7 @@ import type { NextConfig } from "next"; -const nextConfig: NextConfig = {}; +const nextConfig: NextConfig = { + serverExternalPackages: ["@napi-rs/canvas"], +}; export default nextConfig; diff --git a/package-lock.json b/package-lock.json index ad3f680..77fc98e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,9 @@ "name": "kickkings_admin", "version": "0.1.0", "dependencies": { + "@napi-rs/canvas": "^1.0.9", "@supabase/supabase-js": "^2.102.1", + "archiver": "^8.0.0", "next": "^16.2.10", "react": "19.2.4", "react-dom": "19.2.4", @@ -16,6 +18,7 @@ }, "devDependencies": { "@tailwindcss/postcss": "^4", + "@types/archiver": "^8.0.0", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", @@ -1024,6 +1027,270 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@napi-rs/canvas": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-1.0.9.tgz", + "integrity": "sha512-QviPdJImDi/jMAvBfqaw+19BndMd/sizXVW3NnpMd3VJGz++QXkOHcP9kWR/smHG0hNjHeyuHFyrx/5lD0oNcQ==", + "license": "MIT", + "workspaces": [ + "e2e/*" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/canvas-android-arm64": "1.0.9", + "@napi-rs/canvas-darwin-arm64": "1.0.9", + "@napi-rs/canvas-darwin-x64": "1.0.9", + "@napi-rs/canvas-linux-arm-gnueabihf": "1.0.9", + "@napi-rs/canvas-linux-arm64-gnu": "1.0.9", + "@napi-rs/canvas-linux-arm64-musl": "1.0.9", + "@napi-rs/canvas-linux-riscv64-gnu": "1.0.9", + "@napi-rs/canvas-linux-x64-gnu": "1.0.9", + "@napi-rs/canvas-linux-x64-musl": "1.0.9", + "@napi-rs/canvas-win32-arm64-msvc": "1.0.9", + "@napi-rs/canvas-win32-x64-msvc": "1.0.9" + } + }, + "node_modules/@napi-rs/canvas-android-arm64": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-1.0.9.tgz", + "integrity": "sha512-4LGXk2/0HVzE29K8SzML5WubgCp++B1FH3qgl35XmSZE+lLdr6P9VRQEnZ0MCLZMTSuJP41yyhtoiVNEuvrTIA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-darwin-arm64": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-1.0.9.tgz", + "integrity": "sha512-YNdfLBzY0W/Pep9fo2L6RmoNlNksnn05LRnX66W63R3ij58S25QOTcjdtEt2v8+PnCESzqZsYzUo+QPeIR44NA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-darwin-x64": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-1.0.9.tgz", + "integrity": "sha512-ceZQSknTEcy3dOXoekv59LTCkXjvnLsq+VW5PeNNDHEPQbRS5Ervkm1EaDa7WLAjiYWMLuSQTRTHao1dEX4prg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-1.0.9.tgz", + "integrity": "sha512-XhfI0Wwv4llhd6nnWDtY3kQKjq0r+y1i91PlJlJI24ag2U9WrnwbG1qS3+fDLEyouwEVFchiKkTEHozK+5iUNA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-gnu": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-1.0.9.tgz", + "integrity": "sha512-012oiYtKaE7i9oxc8q7nraT7kDOpLcaCmFLzVe9Ty34RHDdoDzbWLrVh827CNxYh/EADX1eSikA3ymLjo/nNuw==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-arm64-musl": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-1.0.9.tgz", + "integrity": "sha512-Ls5UWYFFn63casTZEczbeyEg3vRDRkv9lscuGwfchtY5yLLQhgOB8SN4YGxmfJ5vTaBwZ2YUxBS3NtmjJmFXdA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-1.0.9.tgz", + "integrity": "sha512-hLKEGxV7ZiRHqndePTokgDMdBlo/rDfzg7P4p4QIv9pUhuYobnu3R2NIFLCRghG0nwfo+s2sw+c1xZFeCmEAsw==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-gnu": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-1.0.9.tgz", + "integrity": "sha512-6kaz3w0QMy77PDWk6rJ1ksIihdad3qzEyX2o2oGT8GwCaypfT5mhjr8buOO5hstyLxcWXDScuz56RsINLtBPIQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-linux-x64-musl": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-1.0.9.tgz", + "integrity": "sha512-xrGvmS3v55hmZ86ls/kBLVNMUTYio3f6Ik0DireemG994VfPAwiA3ZXA0Uf1bByctkB3NQ1Sfb+H5bkdUnnzfQ==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-win32-arm64-msvc": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-arm64-msvc/-/canvas-win32-arm64-msvc-1.0.9.tgz", + "integrity": "sha512-yjmVS3ArZeRVCP7jqbPq4rpZa/BhTeI7ELE2XqJg3snICQBDevLZyArxswHkiTnT34KRic33/4fLirrHI+SY8A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@napi-rs/canvas-win32-x64-msvc": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-1.0.9.tgz", + "integrity": "sha512-QlSYQdMQslB81nlABo9wNfQ6npFhE7/O+saCZdqVGueGanyRk4jCogD5EwQenfP3kIq9e+mm6GreQBjX5MrA8g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", @@ -1613,6 +1880,17 @@ "tslib": "^2.4.0" } }, + "node_modules/@types/archiver": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-8.0.0.tgz", + "integrity": "sha512-YpXPbEuv9+eUIPPQWUPahj3cvs9isWRuF+J4z+KbdYVDO3rWorWQFxUVHnwPu2AgKwvgpki5F2VMX0Xx+mX45A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/readdir-glob": "*" + } + }, "node_modules/@types/d3-color": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-2.0.6.tgz", @@ -1728,6 +2006,16 @@ "@types/react": "*" } }, + "node_modules/@types/readdir-glob": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.5.tgz", + "integrity": "sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/ws": { "version": "8.18.1", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", @@ -2301,6 +2589,18 @@ "win32" ] }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, "node_modules/acorn": { "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", @@ -2357,6 +2657,26 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/archiver": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-8.0.0.tgz", + "integrity": "sha512-fV1orZfsnPn9BaSByR/qE67rJCLJEy2Ox5bq7nJh+jquWaNh6Sfec75kJ2T6PtdGUbPQlrVoSVCEOa5SdiTQ1g==", + "license": "MIT", + "dependencies": { + "async": "^3.2.4", + "buffer-crc32": "^1.0.0", + "is-stream": "^4.0.0", + "lazystream": "^1.0.0", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0", + "readdir-glob": "^3.0.0", + "tar-stream": "^3.0.0", + "zip-stream": "^7.0.2" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2541,6 +2861,12 @@ "dev": true, "license": "MIT" }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", @@ -2587,6 +2913,20 @@ "node": ">= 0.4" } }, + "node_modules/b4a": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", + "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2594,6 +2934,106 @@ "dev": true, "license": "MIT" }, + "node_modules/bare-events": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.9.2.tgz", + "integrity": "sha512-AIPKioV7/Y/8KfZ3AAhjPJxLLbY49S64Ym5DakZlUg75qQiTgUq9hEJoEwa4eUezPUlXRy/i5NpsKvo9jgKmoA==", + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/bare-fs": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.8.1.tgz", + "integrity": "sha512-N1nnXdHZAOSstz0XiHikGS4HGMH4CnSwhqWdGQQMqqdvp4Jybm9sE3R1WVnpWVd4SFkc8ryPDBLViNLwiEqECg==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.5.4", + "bare-path": "^3.0.0", + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" + }, + "engines": { + "bare": ">=1.28.0" + }, + "peerDependencies": { + "bare-buffer": "*" + }, + "peerDependenciesMeta": { + "bare-buffer": { + "optional": true + } + } + }, + "node_modules/bare-path": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.1.2.tgz", + "integrity": "sha512-ZyKbsuuqK6Ag0K8pX6V5Txq6XeJRvY+wXucnFGRjiyVYP9YWDpIQugk/b+enRYrEYBJaqLzghRQpXPMR7341Nw==", + "license": "Apache-2.0" + }, + "node_modules/bare-stream": { + "version": "2.13.4", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.4.tgz", + "integrity": "sha512-PcrQ8lVLbiJscNm1Kez+Yp4Gy4AHGcN1lzwjvf5NybWen7VvEgUfyfnXYJ2zNqWnzOfCb1Abq6lH8ti0syQszA==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.8.1", + "streamx": "^2.25.0", + "teex": "^1.0.1" + }, + "peerDependencies": { + "bare-abort-controller": "*", + "bare-buffer": "*", + "bare-events": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + }, + "bare-buffer": { + "optional": true + }, + "bare-events": { + "optional": true + } + } + }, + "node_modules/bare-url": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.5.4.tgz", + "integrity": "sha512-Gxa7UVWBr0/edU1b+TJhn/AZvMQUj9OGspvYsaTYQrAbZA4BOTZGL3LiZxvD+CeMlDH4juwD84+eTAp/bLYW5g==", + "license": "Apache-2.0", + "dependencies": { + "bare-path": "^3.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/baseline-browser-mapping": { "version": "2.10.16", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.16.tgz", @@ -2664,6 +3104,39 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -2793,6 +3266,22 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "license": "MIT" }, + "node_modules/compress-commons": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-7.0.1.tgz", + "integrity": "sha512-g0S8KAD8qf4+V//pr3BfB1aBnARLXNz2Gx+jmHU0LEriUuoQUOPOulVquHKTJ8+EAIIO7fhseNDr9wK5Q9FKBQ==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "crc32-stream": "^7.0.1", + "is-stream": "^4.0.0", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2807,6 +3296,37 @@ "dev": true, "license": "MIT" }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-7.0.1.tgz", + "integrity": "sha512-IBWsY8xznyQrcHn8h4bC8/4ErNke5elzgG8GcqF4RFPw6aHkWWRc7Tgw6upjaTX/CT/yQgqYENkxYsTYN+hW2g==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -3723,6 +4243,33 @@ "node": ">=0.10.0" } }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3730,6 +4277,12 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" + }, "node_modules/fast-glob": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", @@ -4178,6 +4731,26 @@ "node": ">=20.0.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -4215,6 +4788,12 @@ "node": ">=0.8.19" } }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -4554,6 +5133,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", @@ -4697,6 +5288,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -4815,6 +5407,54 @@ "node": ">=0.10" } }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5117,6 +5757,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -5329,10 +5970,20 @@ "dev": true, "license": "MIT" }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5626,10 +6277,26 @@ "node": ">= 0.8.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -5693,6 +6360,7 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, "license": "MIT" }, "node_modules/react-simple-maps": { @@ -5712,6 +6380,73 @@ "react-dom": "^16.8.0 || 17.x || 18.x" } }, + "node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readdir-glob": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-3.0.0.tgz", + "integrity": "sha512-AhNB2KgKeVJr16nK9LLZbJNWnYoT23ZrumNKFDebHBdkC8KHSqWo871JAUhoWC/RtjEVdqNMFpM6qrwRbaUqpw==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^10.2.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/yqnn" + } + }, + "node_modules/readdir-glob/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/readdir-glob/node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -5855,6 +6590,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", @@ -6142,6 +6897,26 @@ "node": ">= 0.4" } }, + "node_modules/streamx": { + "version": "2.28.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.28.1.tgz", + "integrity": "sha512-zEzXb0s5Cds7tqMH6rhZ05lcJydCWiQPEwiNngVqzsxCc962vLY4Uw+mW7od8kDH258k2Uz/JrOkdIAAhSh9VA==", + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string.prototype.includes": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", @@ -6348,6 +7123,36 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/tar-stream": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.2.1.tgz", + "integrity": "sha512-nqsEO8zLZJvrOMdEwkA0QdCLFbetHMn95Zqu4fKwX+hkaTWJPZZOrxx/PwtxoK0MMGQmBQNRW3CPs8IFYQz4cQ==", + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "bare-fs": "^4.5.5", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/text-decoder": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, "node_modules/tinyglobby": { "version": "0.2.16", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", @@ -6698,6 +7503,12 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6854,6 +7665,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zip-stream": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-7.0.5.tgz", + "integrity": "sha512-dSvYKdvLsAHCDqPOhIwk/q5CvuWtTB3Dgpoe0uVEFjTzIOAmsQpprX25InCvrvJsirEbu1OHyy67n/kAj1Sw/w==", + "license": "MIT", + "dependencies": { + "compress-commons": "^7.0.0", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/zod": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", diff --git a/package.json b/package.json index 14bc71a..c4f8d8b 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,15 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev -p 2613", + "dev": "next dev -p 2614", "build": "next build", "start": "next start -p 2613", "lint": "eslint" }, "dependencies": { + "@napi-rs/canvas": "^1.0.9", "@supabase/supabase-js": "^2.102.1", + "archiver": "^8.0.0", "next": "^16.2.10", "react": "19.2.4", "react-dom": "19.2.4", @@ -17,6 +19,7 @@ }, "devDependencies": { "@tailwindcss/postcss": "^4", + "@types/archiver": "^8.0.0", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", diff --git a/public/fonts/Inter-Bold.ttf b/public/fonts/Inter-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..bd7415163c60fb796b1f845663d61e7115084821 GIT binary patch literal 67556 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 literal 0 HcmV?d00001 diff --git a/public/fonts/Montserrat-Bold.ttf b/public/fonts/Montserrat-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..dffac2718869c1024ea49670f7b213d2c1e8d05f GIT binary patch literal 48824 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 JBF?QS`+wV-HbDRY literal 0 HcmV?d00001 diff --git a/public/fonts/Montserrat-Regular.ttf b/public/fonts/Montserrat-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b48180c4e2827c6be1e1acf5e7adea621d13d0fe GIT binary patch literal 48832 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

0zp$B=%d}t-H#d(9< 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 literal 0 HcmV?d00001 diff --git a/public/fonts/Oswald-Regular.ttf b/public/fonts/Oswald-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..87095cc025c40a69c14e10aa47d245e1cff02daa GIT binary patch literal 26864 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 H3ikg1>~q6y literal 0 HcmV?d00001 diff --git a/public/fonts/PlayfairDisplay-Bold.ttf b/public/fonts/PlayfairDisplay-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..da4399cdd698373f78df278da70ace904a5276ff GIT binary patch literal 54060 zcmb@P2YejG+5dO;PCB(a>AFtR_0yetFIKVKsF44tbUl^ zl-IXzIRB!J-~Qx*ziHZYoX~G(c{RCh?1hL?Q$9zNK##V7bfLC^^g?Yj>9uUS zc87K+>3%k$9b^;Qr)+|I6l*4VAJQ;2nYdFUX)AS`)SYCzB;RthGHte|caQ6tt=ZNt z-MF4so5|ObN!51QAJcg&FI=z1*Dby9JgsEidF#&8TolkLm%-jdJ(S@{)|Z+6diFyZ z4{A?q_fu1*>T?d~MfU3K)tboKqUDjlRy#*qLZ4=9Q?&`&XsuIgfkG8pObbv;rTz(N zv*{tyM@%o0{y`n@Q|SzqKB>}QtMn1m2+I7Yy6QER&Qs}ERQfb&x*f8OC2T_T&<;Tl zgtk06ic~ZIkyKJ$_FiaNnlL|W-k_Px4^nb7d763g-0XuY_`KAhp=qlsvqhz^4oRPv$Ht%0D$}#_*OyA4RwbWQ>0?9EpQ__WJ~w?>oqf=R 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 literal 0 HcmV?d00001 diff --git a/public/fonts/PlayfairDisplay-Regular.ttf b/public/fonts/PlayfairDisplay-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2fc72b0a13e1cb2275c4d4a82e920b07d71c3ee3 GIT binary patch literal 54020 zcmeFa2Y4IDng74D00~wQAQ}M{00aTB7qE9yqNpxW60K%ct5{aEBKO{VOB^TX#Ez3V zzFgwu5??Ou96LXs<4bJEXD3Qr;v(x@WXYB#S+ZoyiirPbW&x0@R+8uUfBygHIj+95 zi`m)PnfHC?ecyR^cBKhT(`+PWO`A9{VbFbt`%_I5IpjV(acJh8pFMu#ANl=DP3yXN z;+!+am3_ISOw)SmH7(sdb531s;X|&EG;N@X^2_E7_Yc2!?Q>Rs-^1@oD>f|OwCL;e z&*%5+nx_Bo?B(Zel6T`yH?z+;d;KM=SN`X-5Apkpns&)UYgR2^SrT4brD?zUDd$_( zkYV}IG>_lA_+7SU!}%94Dym$qX-`pydE5GPS1f<@clQly+JAC?{mKo?FWw|(h;&VR zdN1Vz8<%fb)&H;S-qEyYD6fCI>D=?qfAHYFZ))0e8MJ@@rp>E1tx3QA22I=YSIS#7 zq3PN*j^v+}Uncf#pdQ%xZ54&0Sd@sMC>0^mAY!6Xw2C&-E;>b*yqes0_Cl0VQyxcC zz%*?k=^||t>1OR}(regs?RM=B(%o!A+s7ufPuK+aDAY{yKBPfvGI6Iy(pKs=sXNJb zNxo%i<=U{O4-8Hl)~xH7pTCh-o5|PWan*L&AJe*3n>T8a4a+yL(~35%+ptb^Qb4C% z8haDV=8@IrT3beDDw+-)vGF3@Lf99x=cyGpm6Dm7?mdR3MAvr3;IlRhnvjX$GRrYGgE(@Gyx zC4a8cN5-TNtK)}GnLeP--fOy>d)=;%Z#?bvYE{xmFXj64O&gOb`!(w9S!2>g>iBfh zxvJ#Qm~@Id9#ClywYQmK>bUxpX+)h3sMMg0PaTg<<%mxFnT)ofgSi7*j+F5$q`V3_ z#N}vFspP#7=c)7>m2*HH*Qn$7)$wedYqfV(&i7T$f5fM9Rgp@6ta9>I+NILp$W*&a zrTgWz!mExK%JS$Gc}LkFp*i(s9Gg`BcU8Ver6HB(s8se)h|6WF9a6_w26E&G5u#hA z|D{sNCm~u@TB6cfDm_oN^DpZ7e3hQ7(x0kyno6hWPjT%+d8~a$mA_2oU!roP{0T8Z zrIMpUT&PlM6@<87rJba@vL2GdQrk~a+J1r3_8XOkzd~vFE0u=7N@=Mw?pMNf1?=;| zU9uh83R$CenWDQ_|1rmAWoydN{c@x$-DY~;#F42F-FAh(Ti>C-1?2WRcuD_*{w&*5 zY`@ljnb>}!|4{#~{w@9MiR~W!PJVq$zgfRlzg)ji-;~(o(OP{aXD-y2==1g2`ZRqo zu|36^KD|S4(tkp!TD@E^)r)jD`*Pi;XX$3$EJnnqVxQP0wu^1zRqym(qXDIOC) z7mtuWEFKaMhQv=(RO(8k@-8uT98+a}qf(p9(QcH-r1JPCmENw>>s5M3B9&$C zlE)%ol2&bxy6U?sCsU?|7;+2#31Mc z9o)4-QCHDJ`m8nsWujl4| zMM>XBua`QMP5PMlZct~I(ilRNYMJ;zCjX~-Ppi^8=QA`tr$FkE+>diE*QzzCY59vE zH1-^QoIK)KS_duu*=Ww_QC!-IF@N!0qqW4}8gn9X7=J#FmmqQafAKw|W#jv0OX6?F zpN=1nZ{heo<6Qhl9DkB57vGsY`p5TirOjH}OMIXMg;|L`m7BRL|qPlf6ssIXkA8@dLE*llUv~ zCrSUCbMGf=k^D&9o1;YgsLklr;Zgp@4|D#b_@@bOE1t_b#`4|huTitCmll5lH$I3n z>!amzllS{LzRQrGq!h*XQIa#pU-F)cMv8)|GpRC(k_TzgmiS-ee}da^Uj9j{C27Qw zLC=pQRk+8WWor$(#@|!*e`wH4$&Hea_=`q8lr!X7)f@kfs(UBB`856x*CPMiTW&iz zIuPHHs3##~Qtpzi;EH71{*tUaxlhV~@!Oz*l9xnJUVHMr9p~0Eq|&yrSvBMl2RHcE)ah`nQQFFmOJ{)KlY1} zt8}Z9?1Yw;{ga$c$oD5lkG$mlM)l}1a+VnV$#T^5S^R%U-x$r2N6FqEoqMuh@u%XC zvON`N<{@$Nzxd|9?yw{Wk~dhI!-FhN^9(jKa;$Rsu_BqUlMjq=E%SJ zWyU_48k#%)W6mTkiL%v6J)bIfApR0G{tVjhlbTEZ$ueUs$@>YJdMEylIxFd|w2?v8 z_@C89%2p`ujnOMg%f2$!?ighgSEMLFjY*9tEyFQ>z-U_%*BN?wKXyb)yU zn}}_ZXH$|bB|fG5j*;tREu*bd7HA8W>35@ff6r0;ka9DfkIe6re+iy+;+tyP zGUj}Np3VzdG6@`GWORy-QeBgHv)A&Y#i{%BII(GjhmN@{uV02UQAdue^iz zW!*^UzA<*%u%8KUFTNMaN%#mx?dp0ZY5aaZd5^z;FUJaZ`M1#;lA7x%ig7xA!)O_P zDLG*Old-w-IC*Alz8u%as2rPn{Bd&RQ+lioFf`O>%9lv!Q@-5TdnfxUX^2<$-0?I?`YOq*;x{IbjD13f{e=0HjBRI}-c&f&6|otU&-BGQ7px;S>L_-?UQ%)UhPlOJTJ zB8V+lakg5k;kcH~q}8zr;?DJ4-@s<4oh{r!w%AFFJLy9gn@j6v6WqUtt9qHur4zLt zqD8aV%*^s;6RDrWmQ6%^A+0-;&BAD1tQ9gBTt@zK;xbwEbRAc1U@M`g8#z9gEejfK zq90#iD}ff9iRhfCT|^BRLl*~hxdQrL$>!CrV$0Ozyj152z+K$^Y3&(iu+KuZV(mFL zkD{Fw+P%&3J8VAUZ|_2v?QA~nJvO(tgUzq)WD98Tv-!0T*aF%vC?163Ud>IM#7B8u z%?^o&E4rH$#q*$;m22{7ok`K%Mx7p7T)Jc=Ja#R)TY-w<1GCZ5YR*sYn zkuNz^syO6S97=~Xi)sB5wqoRPDgBVVNryLUsbL*kCNuvH^g!|^qzw}vbw0rPZvs`GyoZ1+@ewudr^I`dc!LseC2D+!8s$^XuW+qQKT@fT zOMZhZE9ui#`m~ikZKY3J>C;yFw3R+>rB7Sw(`#A-t#9SHjoDc{wRN!X1ar8{60j63 z1Dk2V#rUq5fJ^DYW$Z5pSAcuC+gHF>>GL<)e~b2fk1`K)jCZa5isN_b|9fB;_%Oa# zct8R0@;g^W1MlW&w5FdXr0gJ421TIii%@DeSLDQB6S+{;M7#e@Yp4E8xv${Y0Y>nP zNZ9W9E=s+qO6iJgvQ!3AJ)csKsJ2QO{u;Os+z-A3vQlL)<=2-%sy!S_nmzzz$#vXM zK9k_#50H8z4Wt7L$N*W4&1_np19CaGf;?aYc90JozzJNGakKY;0^kKcPzZ`Zv33Dg z!o_%YF^*kmY!{l>rIm4A7(_r6l!FRT393LfWokez$93$J^4mfCIzcyiJ)G+WeV`wV z1LMH}m;eUBBsen}OaW8DG%y{^05ic57^dZCfVp5Em=6|!h2Tv1zX)r!7_6l1DzF-y z4c35jz*?{lYy_LQ=XqRnKDYo}2rdFwQPs6%k{Lkf^^wP4RbT;+ofLx9ZTkeN+Y9gZ!n?ij&JXYW@NO@> z^Phlset5SR-tC8X`{CVwc()(k?T2^!;oW|Cw;#LDIuUw58B76F!89-(%m6dN5E#Zz zoB`&7d0;+R02U(6XHv%~|8~K@UGQ%g{M!ZpcEP`0@NXCV+l6PK!NXnfa3B7fhNq@M zbqxtNo&#LO{$g+mkP(TixX0C$zZ-k6=cIzd`u>9{ha|{s!T1kg*wrzd`sLgug-f8-%}%Hp)oP z%mWI57x+LSC<4Vi@{%W)n1divDOzK7qv z^t})CgK=Oy7yuK%Aecn-doq{;rh;i;I+y`wf*~-AF)&Q4&H!`4JTMP04)x9gE5J&wT?JNyv%wm04pIzG_HEktAip2t+&?2TFSGv(?J2<8y|2a47LA|@G=mn< z8h=$;zz!^3C%71iy98WDFE0mIfUj_u?;xe`Vu#)XyTFI>mxKot05891Vsl@^=Dvo_ zeGQxY8aDSeZ0>8=+}E(VuVHhaV~(IPpV831thoYV5CKt84k|z;r~#yWbLrS^e- zFb<3d17HFe1e0jtWH1Fx1=GNEFayj4Ltqv(m<Mn%1Go{~1a1bmfLpaPO}YLHsB3@8$P> z{Qed+d64_O82>&t^sAgPJf~4li1kRs9(7;>W{?KbfdyoMOzKS9v{{U!+050iVSg>S z4qOjz05^i0z|G(ma4WbC+z##lcY?b>xt2vca)A}(0UNM`eBc01;07L00KC8l3PBMl z0e%n!r62^VK@F$_-Cz#U+a+KrSO&g~WZ#3#8C2SVbW1N%`g}W)?0rb}0p#y3BpR;* zy>k|ld=N=Kh$J6Gk`E%u2a)96Nb*N1dMu*sVj%sa-O2}=$I;1sAj>Jw^0b+;B(%r4 zgV4TDjXF77nNw)|-c8GNazEDomA0DHk@Nw7Ku)IiG<|*sJO^GR_Z4Oj(k8zS#or?D zZIDLpy9sUnvGyso$fs!q%0rVr;Dglkbo^QBd6s&f)&594`_J6}MV?!}5&w&}6}$isO7GELqJOVY>Q(N# zi~Wc3_l1KR%!yX+rR^VUhq+3&`(s6gPoc~qa)=1x3;vN>UV$rb(2K3$O|T8fvyviv z=*b>>B1>)KJ|8Biv4@uL5f19H(293C`zmMOf1U(gGUvvNDdg zQu}Mv{u;HvMmzRGqmNa|H`s3lZ-Q;$EzZ9Uc2kq=N3y^BxXV87a*&q(k#jGpJMEwy z2WZCu%I|}Q@{W5|sT|s}8>!t-$ycdImfWu>w2R{pfs~R%lsO#V$rbP7XZ=x?ev8s? zQ(DTxp5zQcm4^FAm3%u<@5hwfPssz+OG_lZVV&en9g1O8qqK+8E=(IvZ259;-leuz z$!FuLvD?+=ADVw?+HQKv^sqijZ%JJ_tUGn5m?Bg5edb-3xzsIdqkP(h)F|sSYJU|P zr9r7KXxT#~sf!rWwP>O1*{&k$bC)LLb8^=C3cQNpi|xi2+l{ZaTPsF)m$46n2#A7m zPys4I6{rOnaa{OW*TouG$ulgOV8rhutn8ki1dfSF(jtOTpTYH&7K z1I__!!8))JTn&toe6*I?fy})R~}ge z{|j9CETO@6GOp!pVZY+nyPVmoO_Vl?97AhK?Q#$feLx>ii#wFg1y+y;Y`_lkfz+Q) z;07L00KC8l3PBMlW?Yo8_k$oP1tCxkYCs)m;2B;Fd1(Yqpc%A)R-P@kp}jlee?aE{ zpvGJ`b+z0@2PR+!X&@a~KnBQUtY<;DTwn!xzy|C<($fK) zzzsa00C<596oMj9Om9lq`#}(tf)J<%H9$W5tVe;lZ!41U zGLrDJ)`gUJbKS)}v1?~=Ej zyRFk_&q5zaD6>;lfyjgY35hYs~E~$D7Kz4 z@der=*>)`1b}ZR;tk`y}*mkVgcC6TTtk`y}*mkVg zcC6TTtk`xe)OIY?HZ0UOEYvnE)HW>CHZ0UOEYvnE)HW>CHfHO)uu|KwQroan+ptpG zuu|KwQroan+ptpGXx(R6s%^~5KVnwCi&^mG5F!z6&{c6*+hn8Tbn_@E2s@ zFIcs0sj)3b>>K#STfv)P8`udg35A@mtz4kz_J zo*n-s^RUmfVYqn)kiDA6em+0;S_w(9^QiNDZ~?dwTm&vgf-V7<;u&AYdc(`X72rxn!&O{+HFaD= zo391ef$PBy;6`v0xEb66ZUwi2+rb^+PH-1^nx{0+fM>ba@4<5%zlh~{1Db6GZ-Q;$ zE%M(6JFpo$Y0vxYKVZK*z7_5ovG;WB!(n>2m)^)Y&pvAUh_eUK08^3ajo?K_$?o_L zaz8+Jc(S5KmW)SAKT3K+A1EtfSeZ}oV?JNgzKy0l#FhIP`R}RwzQ8?4wFpm;sO1CX z?gQkGnHop~>A(UqKqeM53wq=NE64*jU9^3%rii4ZL&EOVrE4U5Z4(^_m=0!unP3RaLT+bc6Xu}tmVl*T8Cc1=RbVwZ8>|86 zfVE&9*g*Xo*>8d~U*Py^j<2DvYr%EkdT;}{5!?iB2DgA)!ENAna0j>(+y$Oy4c;^0 zIq)L$@mJHqgi_8@~o5?c?Mof{|H~rsCl2N`3q1&J{5e0nB}X)&tAu; zHFJis$^63btK13ODo6i3;|mEL9D|;tiwU9 z!$GXWL9D|;tiwU9!$GXWL9D|;tiwU9!$GX+LF8i}^05#3*oS=VLq7H)AN!DxeaOc? z<+ofqd*hK6W4leP4j~_hkdH&i#}4FU2lBB4 z`PhMc>_9$tARjxBj~&RzVdP^6^06QJIGl)|?m$L%A|pGIk)6oMPGn>!GO`mH*@=wo zL`HTZBRi3ioyf>eWMn5YvJ)BEiHtmnj68{qJc*2KM_a##Y`lkTyoYSOhip8FY&lJi$l?i%iSEw~O`4{iWAf}6n2;1+NzxDDJ6?f`d!yMT%hAd%7o zB{~ZaWQ$phw=Tx0qxQ8vq>MC+P^TM-8p00 zKtQ{2Xxh|(wv1QA1KO0~*&H(~=RIZlG}?FvS-z1hS0){wE8jXkJ~um&Dg%<8ReHBdZ&&G!D!p2zm#Xx9m2Tvs&DxsHR6#Ud_R*nI zY2V~~KQfhn#(V0<3O*zLCs*3Z{4|xyHVYMp;k`?aP0Sq>oynC^8=aU;fhv=)6`J$q zX8IWX#B{f5Gy4HkwW-9EWvbSn)PKtMT|L5Eev4S|bPwCGTH$51hIfp#-)fel-;75~ z%X<`Im*v~$W#D`2ZZhs8*C)s~LydPJWi&_}cl~JH1?Y}5w8h8NFMB?$EjsGm{4RA@ zv$lqJ)GOheyt91EvNmyN4=s{3lo6lgIT@vr_mXc}S&pgAXlEB!Ihj4mQXW$I#<_8( zlwY!b?{DJw$bB9f_(IkZt|kUKm-TK_v;o@F#>}*u=WPKzC>_0b z7wHnN(5XRwFJK|wlTKXjdeULMDV>#Z*O1P_+tSgf*U_R`Tz9M5FTwAUzZc<~$^9_C znB337FO&O;v_!BsWJInLl<%ZE;gx*9{!ET}@1LUrj*2G$xM(rcje5^_3dagm~c zS;#L2ydFdXIE`6G^2P$K*L_|CkbrYJ&A|_i_D+X?YcQFlgD$kwHr@d><_>+ba8H)&i9H zBS(TL=!woROPyb;`fFS#=^jx$(76tasjf9@lE2hDf@AXJ>RRccCHo=yWI_V37G30- zc<#GO$S*o1shh5%=0fsc&lO*k+C{%rpU?TJ#$GJZoI=K0Q-4=$+S&YAo6Hy-o}_6{ z5Y){#cf`5ge3N!KpsBS~yuYhIMY#ZXmOYoUBO}H#Ez|Ui&R%oAY|1(3FJF&mDK(i{ zmDB~cfj@atjzwJv+NSA`$xL;%%yp`=a&Ok}<@Y$PkM_&DbBPwWGZKHQ#f6S$nWI0( zTE|!Q*GpK?PGe7OVs*heB(c{2J;z4-P6dvT%$a~)5s&*3qn4x&BAu%qQm40 zF}ZrUm@yz%nUunR!6lp-0wW875p-mU7JYUjYXY~G$sA2W*MArLGVV&i)(Qmc?(tfA?f$<{0eIi$)Td*5B*i;*~ zF&}N<#U2%+l|sxA!i=O!Ry=&hYKIo$giXX?J9)nF1=hazY5lBS9*4FbWX1B3HXR!? z6TLi_dBc1nvMaDUtI+Cek^RHkImDXIXMNFyJVn^Re5FcT$GTZB79zxR0z71R|1PV& zk$I#^>Y*;UchDrI8!toHgZ8wbJtz*242rLg+$lDj%zyo>$y{=z4e7?u(|CXX8QNPx zSx1TRxN1eHG~LqNBci5Ola;U4jLB+sbO?tl*eb?vYO9Z#ameh(KQ(+?$R+!EG}|x_c~{M4DB&oNiC3R<9DJ9NV2G ze0e9+o+ZBi@bAn*H+xK(#UWo&u30ykkF2aMgFBK%q9~+4(ia+M&ktsIPAJX} zg-2{CF886*h#_YQ3N)6cD=Ja4xhYa5pg<$^;<(Z^5UiVYm>d8gLn1{ zCv6*$Z9@*Fw`~y}N<$koz8@NwpjTw84XVoa9xYfj+M|f;HV9fPMCZT%=!^%?%ZoL; zQ*?yLq4}oTqT<>O7uPpmqCfTT|FYpb3y)*D2|3A!ggH&6GwC2O85^ZD-rPCJL zsG>F^5(l$7& zETJB963XLPN9^r9MeE~{QFLWXFM z8Fv@=4~23qj&wEfoSxz(vDmB*|M{1eHRn09Y*m%{_08^JbH3Ycaf;mB^qjoll!mjv zJY)Dvas*~|GXN`R6oo4q7F{#zr~l&0%Jn#wRg`0#V6;w}Qx^WMy*xeJTYSd1&b{E_ z#R)$A9zF!I;}cn6Fh)?Nj%%f%N{c0!k@h*~9nC?Pc+Q}>XRtIyeb+#=bZ}&%ae^PA z37$lu38Cn~h2plO@BOXC$*!!qD*X0iPDjWGxRfcx?!|me}MKkCfi>rLgG~I6-k$oHtP@2 zuJr8mkwqtHXt_-+m)V_OU!!bletG!F4^G{#ZQ_UF@_eL2*Ogt1AJ!i*NgudW(pJ9o5So>G4AEl)G^rZqKYQE>_OZg8pUAovXTKx>DaV_uJ>; z=aYG?VZ3GRxul_@_bn2^z=pM$6GnLMZ5QQ;m-USDgt zv|S85{P;1}dy6GQ8n;tAJ(i54_~ELN{(iM<~j&VhlN564i+05~k&X)O&OP5FwzO3wcOPA2c zVcJq8BeMy)q#>h|37mNmiXLyNN87|yjBzEJX02-;(<)a(RkmI?*K&-8P(}mutk*To zZ;i|xsBpF}YF@Bd2#5Za&#{Wo&ZK<%!^l*WI0ybjnn#%Mwac~G_< zt8P)&In;)8sajI1nIMwZuYvY|sWv)r~yll!EjmOe2rVcgyW4`ReMQgc70Ax=jm z93?t~%1_)uPPU*2B#<_=N+g8kXudG}3zd4LSCnu`zS+_f%^%-s^=7%;c291etEM8{ zW_4$JD$4ml9BQq0W<$w9SJYWEwRYyblZn#Ezv*daQ+8+1>gp)A$e!&FR`;!}>XlC) zcm^vz&|kmy_;^&TxzjO&O778e{5`&b2|t zF(>r97?t@R@3NlydBNhK41}b7<}80-^RziZdwJ(9}!8MV}MvuR!XW@Y8NSS40 z$o{PH%n8x)7fumvDN`uzf@-I-M=|Iq?GbadRKB!FMt+lAo07_x_Q=R@knh%}@})g8 z@?+{vXu)?>4(nGy2kemaBrPWV0REYb@Q@TTsN=y|X-VbiS2(KdAMoW&{;7yuXOS8R zrd&dDF1@<4xXb4&#q^saHAf!QFOb1Fh)!Y+m5w;<;;EKy`B_Z(Kr9eH>Na(MDcPsl z0$f?)mW}cp*Id(Wj#}&EM&tgR8?ffLcxhZoC@tqJ*6Z_4l}6)^4EsDH>pt)8dHB%f$0XP7=;zU& zVxl^PDIBiSbkEpuW~?Pjv{#1Spsl06L^NQaWf)H{H9{zSF`M4yiTX$bx+v+qe;jjL z#f1)^JGahPKFb*^vW{Hu@OpCVy%m$@nA0vRGu2mG%MdAVO`gA{NW4Mv?exuMIpqnr zU4P2u@*H`p*rB_G$s}AkZhf%WNhsQ68hJQ3_ZKZ49=a>dv@@-?LLYXT>nis89!_TC zHR|yrB-7|yNIqFNcqIiTWOSz0#n3%kQcOxMrGmS9Hy<#a=7@NnwZHEy#P#+Drv|){ zoV@R6+)yNH4c2TOt6EzmJ1VM2Hi<{V4j1!d-IWt49(jx>bFE#n!MZ-O;kQSd<^S$M z-i@}ZaU)kc$=Jx7N)O2xNQ6GfIjBoIi=z_?g8`_1Y~C0Rgu5FV`NC7F2}OARym04r z?c(m=7+F#Qh3C&NYrl@h9yxpLgaQThHTgTKcw~r~u_))I|6=+X>< z#dq1ua>x3j@_X$xpS3!N#7DXv-8IM~T_YZ7R-p?iLel7^D-$jw8U#SGY&b$H!l5i1 z@k6VS-bl06OtAL{6v~c#8{tPS51piVla*mS@X$TC-h|Kyk!T zI5j)i?#ZcbX$VwV{B7atwo;F)$kT%|wz|y$ueUht@dd0lk0ZZeLjB15UUycu-R5#e zOKPgiBax@<9*;j(US3b%R3A)`mZvI`KP6HhrSeM?`RT$>m@$>Fzn97{Bxst-Pt}ty zijBE^qJB@ReBivX<&gn(-*gcyBA;;^#UA_`npW}TXNjaLE>O?s5Y=MUTT^6AOT=Ym z#5ovkL|sZ|K=9F+!#sl9pK#l5|GB^_Qx;99YA+@ku1GkfMN8F^g1qvuCU zD*K2X>J@!uzS{CUXI9O4OMgpcYsgzra$*(?*1z4}W-kv_KzO&mAzE8g*K_`?#aH#M z`+}okPHfRib6#2gz*&us>TpJ|Ckh>S$`s$Ln@xENqrR4UyCbW1N=whm&d#;E-Db;+ zdJ2nu1)d^venCO&(uwoe)HrJ*mOy`H-$k=$Ux9NhWvrHX4sAeYh=L-kVfB>@owo<} z>GdWXPvh!osvKf2<#?qiVqx%E6vaGhX4+!7mWf8b6Rh(4i<{jBSstsNo||j!Ebp8t z{N2@+1D2eOSrd8|H}sxuvK?70DUzO{e@9W~)5^xI%E+Zx;gn7qv`(Adb@7>JULsWk zaxCe!&tyf8>*U*58mp_Hs(G-Y0b(>Pa#&EInA7eDS zLP|o6oMy(7J=EODgB+B!a28deXr;V*944>J6U@v>U$?Hk!82S}I^JFp8XC%SJDfcx zYhF%HAm39`>~;CfnYm88YtCGsbL5f+BD&J5msE-`IXj2i-JU{X2btKJOuZ0U=wzOU zVl-@pl0p=JVxG*iLMa@HTw-i$)+9_ReP;Z|VDMOs!OxYgjC=KD4Leh-=1VU&FKKV9 zPj~yy7^s=sRyScvpexcgHK#OIe?{fQ>aL6CGz`_&4mHGP*4EC9MXIVI;p*z27NwRJFP zr1@P#LtPRtTS}XXi~U|#ZJEgyQamBjtaqcwu>KDFQD!jdjz|tDbtbtZ$L<);Bvsm@ zzQv7^M!Ulns<3m{URzm7R;a9^x2&Yh)=Mj3jWK#nc_X(DG&%E~U5z6LDoaw_2>P1> zwX>Vw9L>@@4DE(qVNN9S^dnkC6jf__I!|>Cc{1{?a($cQSeZ$->^HP%La21K1-f-) z=IC8Sds2rc@1x{a-XUF-$c5kdNN;feZYBRlzW*sB|9vUPO8$-f!r!a>vF)u)wU_!$ zvL9pWFWyUe=?kMbKcIgx;v!RsGc?NwELM~elPvkDC1E#OSo=}tBVKo@w&IpuMb_EkZtO1{Q@~?f7h!2P6ieU`sxlV z0$D~bflQieX*GSrSsrg_EV_*$8@WF zOO%Mt7>h{HR5yG*J!2cD+99qx`i|IMDYJg;NdeC-PtJK`deDlRNrjeUEd(o=RLFpT zizKT-&qt+{2FA#U81`1X?yx>;_q(&}JpMkL)0Tan!(SXI&z};g2>SZn_COKlX8Ncg z>7A;XBcC~SkNcjYxW{KQgxhKTUZG7m%?`)(VASp;l)xN8{x3KDmpiHtC-1>y$I9*r zZwYCUEm_|~)E8l$4di82&vxwqv|@~y&cT*+um&gT85}oO(d+;OU*eoo`oQCcSkt>wc0wv!Z} z-MDxHRvkLifBuIH+5dl}_hQ5G+O4wp1bthqdT;{ec9I?pG#h$HA7p`KM6CqI*Otrf z;9VU)$^qIgy-Zqf*q5Zym#YTUWCd#@^7~eIcdzd2J-fU6?B4dtliPuAZ@YNevWwc< zE?Tzi;x^}nH{N)`1vlP!A@@`DDm}DP$_jIe-zXU}@}-@Z`Pg}B)|2Ixo-^_bm| zg68H0tz9cRI#zTw4Gc6jj~_3>qZ5Rbk5m+^vN^NrC)JHx5^G$n+a#?Fie1#^gj$kf z7r0LCIqAH0FjaTc{sKAQKdB{ZH5iCf8Hu(Uif7C;;jzXV_l##m!SlVxo#Z|m{;nj#HD**V!ObnB6?R}~xT#aAXiRhlQOedDZ_bIxe2_FIc0gBMI3 zS{<7;n+XGQq|rVN8-MEdc~05B@BR(#Gv)pDYoqPc52^Nja`N`o(Y~*ECvvg}S}DJG&x!=~YAPn`bklTHJYwoE7Mn+>*Q_&z1QMvKCkA9&3@B^C}%8 zehhzkhGNKO!qT?l=E=1WCvl2Uo4Ob-tnm1Ku7E4oV)ZwbIY)ifgr&=_=+N!%klPz6 z^g0SNvcetxMSmXSry355<%;4?8G4j&@QE+dmTn{sO1YCup_IdURBRhV7fDwEnpALG z1#KbYAIjTugKFVZdU0D#sIIJ|G}05UpI+;Z=4ZLGvTVj`DPLR6Sy9y2P}Uo*7|`v$ z?84rn>HXosnrNh?D(o(Zbyd{%1T2;`Yet6M8(1{0ZMZJKGF08>_tbV&)U+4UUKew} z5`2E9268UrRL@C9r&=wBdrUCK@Uod>DaS`XS8;n(cw0@v?9$G#a!NU)*qX@PGsCUz zuD%TejkD_u+oFYDPl?NIDsgyf{m$~-Fy=v&1eFbC#s6O1DkTT5vReea}6mB_-8pna=LgYP;LM zY?-%K|Ng%?N3N)gG<2kO4B2g-zGgAg`8APFy*B7ohmUmhOqoE`X?TO;?ZiykduIJH zE+2;2kT=}lC2~BbXI$9ddU6L(>37u@rQc;xNZN_tj>(sHLgr&9X0pQ`7;TraCnLXb z?wI^kJ=lrM$j2WXi60i*brU|zXhi#@aZDd96ss$QfoWe|Gq?M7G`M$f|JqC)%98?2!Y`g8ZyXM_{nZ zoHoa2Di7H!qc%_2=BOwVmpEz)&NG{5xO2Q^zK};!*p+V^xyKYGOaJk{gcPYCBaR^|M_Rw z_@vr!%k_u7LhP1uVgIEgoa3%9Qc{s+zf4L+SwbpaEX{J|*sAj#{`?}ZtHhSAn?zxy zt?Vdik^FF3LX{&g=%O+uEk_Q`^Ok1kWm^j!1;qs(yE|QkD;6W~Mjw=1OM#Z-E=Dfz0Q9Ar*5Hygzza{6f!=t1>c`zEjIp4b7%Ja7(Bu!qYtZBz`gS=Em~QGO38G zm)6DB)QjN8>P~-J^0%HbVhK#_=$l`p>#Q?A#Bu*TdCWL0CY}*CwJ@&ayfmWbu~FWv zl8+c^rI4ZDQU9$i;g4B}n(yL-F5@)%@6p+j=R9)tWuN zrM=~!{)w5xK&W)03gfsv-kD7MGR(4Y45A zchkM}eTw{osPsin5T(*xDv)}tA0ihH3`=FmUen*8r==Ym2pKsy>9wi&Sl{Y!VWhmOGP|_;WVDrnl%$!B=*22%b}R`H zX+y+M5#38XfkE(3lTfBFzoLtb;U+Zry|eM^Z1%T zB-d$migoJqlpHCa@kC-I{&q1E8;W9;)}sZ)n)~_k zVdC5InMccjcgEz?6ajdg?2qK}KgwY}`?OgXb~GFl@;D9dBxEwa*EEZGNSj*OKIR$B z-y)12<*_Q)3kD*cVyQAD`rT4}B|3J*#(nA$I0E)jbV=`EA7)0JrKfA@WuC$K*XuS6ymBdY_6NJw@GGo-`)Bj*sPB@tl@Nn4XR7R6N=qM0>`hirwLd))wwHQsJrjyP-~Z_zYIPU8qNal99Na&6Vx!Zd@o6A6ArT7=VA0QmQ4OJiQLNa@No|FEV!{iliIlfOj;idp|xwA{$y(^6!* z*3SRS{yo;XHzXp;Dw-WLV(yV-ELN%__0X9R?AZBmk02h8%&P}ct^d>Co|9W(&$d;U zgo|`_WN?TD=S-@6dw>k^$ZeNkp(=^@eE(wQ9ypfQ;rEC0mTsC{2&E<7_-ApxW zT-iQHeoZ(l+g#vqc)d=yKPx-us~LG#Ti91v8erVTXzxAh-IhWb0YCXOvA3&dH8stu zHquC2TLkD^Du%i`XH`_p>g*b-$e%WE-ZTk0hixM68dA@ocw%_MCs3&gfM}Swp{MT) z(_&z+z`8kgr^3KDZ<8LF>zhq zj63EDk+C3=adxD-$vM5E_6$#~&DmHpX&Ir~1@)yyj4jx(ufEpm*5zYfp5Gl7KcTI} zO?d`@Gj6glH!*@qaut7%$ykBHvNQeT3A4go1AXq_SGdh~UC*rVDS5wScxH2RUHJfu z78|G2?C$c3{oS1M{fEa!q|WevbGj?#I)aB*l5zLEblH z+$$v~V}kZ_@tgj3Wq-J8AW}EnQZ;qiIgO2H&8%y0$n#`oWZ1GY>{%6Mb>$TkJodc$ ziMqY8u`JqOXBEM5O|{dztK9j*-!ZqfbGkV_(~_QK6Tg6=S$a_M>jP6_fm9?Ic*Toq_eLT+?*=+L^H8i>9 za#``)BWLMNYZb3*;_Jmldb3*lDnADRO)WjBbtP=Ndf`7wV2Ap0KufEbq3ann9Yt$% z+$|N|Ga?cJU<)osgr zn-{g!&8*L8s`NBh#imvbOdqIfn4@p;ch__;DYv?tx`UmQ+hcVTJ6gM^H@45M4^M4t zn$zpHhE}v!O|2W>*D$5Gqi0$}-C$JGA`C758#$}uM`FB1gx#6s}l@(`Bm0YQ> z9OVkSiD!O#G^z7WsGH=nQn?PGe#*H$eVZn!bYSwtS%XssXC3n%-_IZZ@xMyYFL*1) z>Cf|R6seQOIQNMUUog7GN5=aaRg3=2`7$RJE_}tC+a7rJ+CH z{<}681w`8TKXYoa*rQH)|1{2+K+AADEKXPHGFMp*^7PUTv z_dkO!sr8QKWUJVykNm1g{Ktq(Y#7VVDf*Vch_8OUQ%^f`?=dWW_d0`aHPG#O{h)gP z$6#S_R2RZS^{lfg`8-A`Dn_rt-KfLOGD(!a#O1y4pG${lYADYkB|lsU<}t2OH|uOWUQxbNo{l@y<%c@^de}ZbCuS zrZnuWw_JBoQ(Ji~P?y`_laJg4U$xwanUn9wCcGPEpFdB}Dx+g4+F)$B@ytmX!SejB zwub)L(1M{@&-w`+tNU6Ov}E+O7Wc-Y<0~6x%%9QFf@q(nrY-5L9II++Cu@Pk!DKsA zfyUzosFX2=Zo>66UcgM631Npd7Y`LSIF4gwz3(ViPOX-#JX_!L@Pn8C{H*M(?1-1Q z&OC53Hz&o(r9;PZQa(Ei^9B0*1j|OW$N7TSRP{Wq6z(2Sd5@;@Lh%vNgu%A()v9E< zqWHgvGSN%kW2roA{2O9O)RFh=RGuss5p&7=KdC&vTq;(Je<$yWRGuyV&wSggnY{l@ zn^#wMI-C_}$j;z<+UG3pge@R__o_#>yACCBARTVtFHu-8C zylCgBYU&CV^Eyt3U;b|!MPiXC)A|1^rJpOuq$TC@DVIdKxvT*9B$S98LgIThZO!HW zreN*#MKw(e+slL5_6(aZztkP}7dP1DZ9it2P(!w>yg1Yrb=mc@uCh>-NaKYMv#?g% ze1XD3d3$(a6|=>V{tkLwQjOOPq*pKBEJmFMn;p`f-JkIX^G?}6bGk`(aAe{G;)Ep?3}Ni^APW$kcSd@;s{xY^H3JuL}BIBl11n;b>>M(=JN7YW&rC zIhH3(`Rcww@guR?v_`!z>9ML8+zcN@4%*{&FAv;J!NIO@akZzcy`{`v6~gJSZu6A& zmDf(Iojlw$`%KdsyQQRU(S*)^Z&OcaeXhUA6sfeML27z}3uX}aLkPPgSf{Ne{x#T>kr^i5)h%!KvHF~T0^D$E2<3JZIPJ2BEfH;SS*$@URW%q+J^L`d{tw?D8Z>QuK+zMX}hRg zPZ7VlEWffW!;)6rS|Eu(UEe=@TKB@vV4B@h7@O1E+UZGBKU`(^cU0E&LhAn=?|;vD z|G%Sq|5uOvuO9jTtsWUU5Pt^U+QyRw710qrjw8Qt@L2h;59BHzt3LjW{uRzgwWkEW zEHSW0dHo0PN-Q6lieDCse?z}NaUQQsp669_yed(w&Np)Y_lfhDs`HN#Jd)?9;l=UI zXugX6YrajIt!b^w2VjbW%Dyu3g3IRQYc5jf^~5ja%c+~CwWh2w<&d_uxha}>W^tvv zC^I`f)|~0DG1*+yu{qyri{vy6dGmAIigPk^OG}C{TeMsL9|8ZR+vwNRtkHUaZ)rVk zk@=Ik$BX1gv}b6Ne6J&4JU~9})c0`j2s!e9Z+%)Yi^b9swPJg%_S>OQKId}EpQiQm)njke%L&_@|$X&pNgv5rQjj_S8? zjvJqBMG(30x}D=?$wjK#_%g;% z^}q0KTraZI$m&bEGMfibZuwmgDZNDa5oLbx7*D>afCFPlN^7%pAk!l}q$2de>{PC3 zqYys~u3JKiI%1tKXt8ARW?7pkZ&}nl&Fdq+$(v?Pm8M*`5Czs;w>wuaZz)KY>+v>K zh^FaYFHT?Ji&i&ITduo6zaS4MIgn??@rtxBwdGs$f;rhd3}`JE&C`lX3OxSeNo~Ru z?y$;&ew#J_3eK5qj$Bo6Zb3=W2O503ken z1cws1djFa4UinHE3Hxl#{ic^Q=ggcrGjk?iPS57QX|d2DW;@N4^MT(1u0o>7#;G!B z1fv(^-w9BI@a!jk;bj&cK=>vp+?)mbj=%s5Wnondebgp$ZJZ3cz$^wy&?QyrM!LF2 zbh*Qa#fWy-8)weEu}eGp{>?YPkNUH-;eF&IDIIuQwmy;g&ZrLway+RR;n7D6iIEKH z+`wfU=n6a`q`__h8D zxx50O4WiCWb%~Ll?yXG~Dpf_(*6zN|Nv%0PHo9%RN-zn@iES6i4m7Uvre7?S2T?G%`_bI$(_B`f$HuJC*tli2- zWf4?T%k|?(tLH`#%scU!p`n?0N#VB@e4O=d!C+gxQ!o^ZLg`tXy{@$Mu5GOJ-JK{F zILqc&QxEW}_;=Iguy;Y@E>6AK^Rd~^13pDpM*7dXoY~Tvn`II2Wg6}|&4IA@u z)5Bh$wTdu{{90jZgM{T%bY%R&X0r*OK~2U3k3K3q^6?KT90yB=ednQdcUXIVzXJQJXOxN;Mz>mn>5?)%;{K# zzIPsuuZgk0?pUmwzU8S#q~Iz?(pzP=#}SuBTIED+%sm!GVr?S6F3$hhXxFfCIsGqj zJ?VkI`ymc*3^k1TS)xY`n&6~?oR0u}GY|uM)+a9BWt?1|e!qHP{s@qr+f{J42n_ zk+8ouBJ;OaI?~~2_v(P!sq?t)jV@)GJ8qN9sV#fq#{3hsHUEV0GA>(qbvC!tVst3f zx@7NY>U6lRz7ESEYz*5%RZ4@rqOQ`D^#|kSGMPG7B`VcEugae8s(qk+-=>=UrBbUI zzvjkdxVJ#NNv4O0qN;LMT{b8}Z!D;`Uc$`Jrc&%=7;v-C8ups|39R{~s#0 z*w~sRlY(E^#@3YB3%7=_q5;EEPn%wUJ^aQS!nU`3zx$o zzTq`Ki-d^vzgR?yyEIn{UBWuN%0bLp8m*?6(BI~rM*8LaxUlY(SHh2BdxOREAs*DN zv3S(3rOHY{Zp@Fsqw%JU5ZA z3q9x$RwwjZpkC++=WFTQ&+lV>A_r~$RQLhp30jmI2)FN^C|nUUh_bj%W4i}xt8&048 zUeUqfLw{6&H>5_8%v?vdTbH8Ug~PSj6wH*PiQ7t{fhX-Xo16vkJG>+4ANj@%xu(VE(lVh zz$j?Ul-xX&e(N(pLFh9E$9j6kf)Zxs?<+bbsFsE;!LMR{AlHDXLm5$EqKqmb^eEby zVlPlYNhsX~T#{Pb2}t}Y+_h#q@QT@=)=ZYqEVjNAm?rp#jrSw&VibP*UATab2{002_%hW63m&jpu17KF1%K$FajGdK;hL*q!9K!bs)R#2N!v!%mg0uDd2uZAq*h5pHQZx@+X* zj%+YpQ%(~KRsJTMyS#eKl^0yPKU=r`iZjFGSF||2T34Xs+P%YHz9!fFs3{thLGxt8 z#e3`1sbl*L7fjXp8-vXUce2+H@&1RH246gcHyb4`b5XL(1fQ5hnW&1fn1u~hOcsUH zZyYF0T39%*SCH)R4>0Rg0&^BZ@fDr8dfq1MAlA$U0NqNpownL2cXF);6;?*g4wLFpzP} z_3^aBQ608edOCvjF>SfaOFE%vzqBoJ;q5nzIxQWzqQC!&0jkxB!V_|tSqKC^SzmG(%oGpRHRVoj9J}q} z`i)l)DU^bsln-A$&^h(_tERen{o;`GJqI~o8n2_Bzd9)#(*d#ajRHw#iBV3ft_bSk zg2CciW!Zr;aB&hwNL%Mr?yJ&=<8GG?uURQWF#y?;?T@Cq0!_VTRk2uCq;4dg+!!lg zv=24#6dtGDZ?P*v34OfQni+_uI)e?Ou3Vu{v%^~sqfepND=Mn((at7!pm}v7eMzO- zzA6xGs&j=qHe_no#qz(=SfR_Vxy}{p+>oj1iIpbS859*Ywpa&C+!4==0xlxPlXt}d zz{QL=)UhCnhRx$k)qQSj&YkG*Kap!Lei@!Je(7alFK=%(ZWBPZ zxxB@qbTW_WkH_0WeB9*f<3ng(aU|j74~3v?$bfcd_RttR42QvoT}`lC`O9SNWGXvH z1YUw4k-MNJH;_yYhtfVjY|OOc_Lommz& zGb66}3%}VEFr@5`n9ilY+VBMfuKgH8Q<$prU#FMm-(!CKK{t5u2snI5 z^S`2aoz9ik`Ym1A{J(kJWyOSLZVydnyVPzy&M88XK44QVbW^`rhdCar|I!sI8`p}I z!Dfg%)4jdvRBvy}R_*mx+w4`)vLn`YG&Oa0HZ^q^9W}vFjm=gA0)ixvl1mm=k*h_v z_k**}A>-9CaqFL6k+H+Uc)1l}CwLgvu`HCC6R}u~uKVPDXa=?9BlJb&v7UC(XCRwp z2h#v?#>+C!2-Hcf_T8PTw$Ft;qbXJAZaXxIP55=T&Oo5krt?oUG5Wy15B*zO&E*+b zzneo<#&?d=uc&B-t!Y`wxh8FY-jtrE6S!J2Y|f#U;eD@`?}90ZD(z-5a#K) z@LSGPv9Y_jmD{l7>Rt7+i*&+o&$|+b_JxGMB433bOD3Nv$!T|C&r|qhaaR+sT?<>t z&v1W^$#YAuzXg}wXRBUzJB`87g0xQ+(z2aOcEpJ>4v%O=y}qh7R$fu*((40awc2kn zN9q%0>2-Bx3%jsLiBp)MN5vp7cWEC!Yq_{Z)iCCF4kuJC7hA+&=2EZD+~9UMn04Mu zGk{eHdk?RQb_rIcEi64Jd3CgPXbod1dN6DK=oP2<(!y8X}t`ZT77Dd zN@sGJ%?`VvJn5q(t(t@cW6_aa5_ z!gqu-qWoN1Y?&6)3T}P=4wK3>W))h@IlXYi^2r+}(;1!Ep*?M3G@Jpxz6pGVMp++s zqy6kHYbX+mN#PUpZ-JB0q~(;{^Yj>K5}JeX-0cEMBmEmZy;n*v+(-AKuN5>{h`)pU z0eGpPe!Z0b8hSGj0h%O%00MD}GP+YdBH`_)(s*~78++@N zHLVGxRcf^rI<3{~(uV4#JykuF9DPwdy#n3-8bhzV?Lf%0JtfD`E1r(@*mc^7*&Na8 z>^%`i^P-Oaqj)3V@h|XHY^eg8qc>{|4TIV2V1q$xzhwRTQSrudS3@}5;8NQX5RfsN ze+@K$s|35xO!K#{Nb}Wb|J~xXpHB0)cv3YrE=!zvzNjC49!dHHKp}$LKSg{%ND6#7p-tNMm*WD zkZ;sQ>|Spv-K#XZ3b!@vQr4gjM&RaS0HAag;BG7U>P;*bfPTB z+9$kEt|{VL$vD4P3x$KOpjoR{%9Sdwc&EZ+GzJqDicmw+Xp(TvDQqTRgj|;6X-V4S zx^lJJ74>M%<;pU3g_u!PU}K^#t7z<~ve`9&E5UyEC|-F!K(53K^k2ez3-@E*{|bGb zzK30yb;5V?`uDTKOTwGtpm?v$ChL=JmhFf6$vYEO}gQl&fG1HvsxakJdo8}ht4dxdue#;Tdt5$<`vvrqs z#(Kk*3Ij$o-N3il(Ad(NobM#}u(lY&7`1j+_#9vEj5{^VTQJ2`2_(I~jq$?Rtb|fE7zM6cmN~rQxwNxFd`c~EBRnJ$w zivRCclWKLfsd{tuSE|2O{bcoXH3l3ZpQ$-jb4$%b#s9Uk+D)}TOu15LQXi!aXRMW#v zPd2^OlyBBFJDP*d>zikqPc+}r{Qc&aT4XI%EiElmEmyVN-|}e7uUkH96DoU(R#e~me%jKzR;R)i?r3XO|+e9`=_>N+n(ig4cg9r@b!Ox+p=BXc2*^d zuQQ~4-aFLKzQ5_X<3pU1Tm|hkPs7PxJeU4qX(4M_z&?fS$^6;;g|hE~f|mS)uJR0N z6AmqW_~(qc8B+OKk`V4E_1ydt_Fs}RVJE)JO*8x+BMrh?lEAAh3E?{FOD|Y>4Q>St zq3agj68;8Z{gM&K@%>@J{5Q(@6eHe_uwKMl1Hwv)~p1YXdC@9AKbf&q95~M(-jv%)?&c!h#8tTH$adpB1n_sL zTP=MAWj#ikg!RNqcM%!F49g9DV<9gBA8_l(N<2JU!hSQpU&Hr$gpEnzI5X!GcM})=SLh4)G5DE_NFDaXYUzK%{0Mi5-X=!+ z_gK5hac1ZY`bLHDPe`S(9p?>mxWn@?!(vP25ZtVc`(W+>y#5}qMt=ZVz*(F_`XkCXi#&Vq?ZG#J zJ>N%QJ_I2%gR>&+i`8fl@Ej1zL3`^-0R0mJ?YY6*Ch_g1d6aWK>1B4TS^8jnz_}#+ z`h-(t6L^{s`m9a3hjc=RE&rCdo!tMc;4fxKT3m}Vu0i~dNnAV*Ui41VCbK|>F@PPr zm&hgLWil!_ur_W$`}4T7&e|bIoe9%($xbmr{zaJ1e#q}7H~SXt?7F#{-hee-2>9{e zsJk0F9%3+fqmbSM<0fgGbIpLRGW6#h0#2NcvVfa&BKK6M@H>w*l5aIi z%^~(d?w&&na)`rnnngYQkmc3@)+x}$#zKl>KK^An`IqH%E@dm~F#^rCt>@+O=j*bx zW`C*tZq#@`+Q}dyLCeo;o(4_%QT_y4=0C3n=eJ@ba+oE15qme_>W9qsAifhEs`GHi zcu%lim@o9hI7(zO4nl8#4N|dQti_i>_#k32_>LFgT6j$>|CHMqUw*rr_a0{nHpxn}bpaTL;yg#J^`4_b18)(D5 zpxDfb#Jt*oTavWU!=gAd#b{Vp`)mQxMYVh2`_TeUx+25O`x zYNqVjKO41E2kutf3feaVdREZ19h&r=7y;avpuCdohE22?vRu4Y2U#|IlB9!n;zsa$7(xGtdmDPJ zseI&a$ko4!UcLiwG+c+12nvjStFao@;Ptf~&_30H8K;YUi+md+)#Ky|ysG>Fd60aE z{2y``?y)?EQ4nJd?WSw!T8vnaK(e@wT!S%CNB%E)hdcxf3SgZ6JK)pTh>G^m^|Y7v z(G9ep4$wh5gb}ukoFvzhza}?eHFPyz7kQm@;->O2?y6ouN9cugGu?u>zAwhT%S&+A z^isMFcZ_$?op@*SCGrCK0%p$_$#2NN(_M5o-9vM@y*y4Q=p@~X`wLTan$9RXcg^Jv z<%HfoS^u8d1BTw6yAK}7ZSSj@n%zA$*uO?M#67rkWB-P-Np2h2v_Y8Mt2{U}naX4v zWm7EWq?B^+V#?ViDaEnvV{(}7ll*r|HMV_M&D7-hPBrr^u}+-xMP9`S`?wW}q+kQ` z*)y4&%gs;D^AIgO#^-h($`#{DX^}umsXUgOo2{7|Q_RjF%9!H7VdhdDn3&5kw{mRu z;2i%>vMk0F^OHwd_&i`U!z{VU@reU0!ptPkpp56YXJ&R<#d72pmM62QrCgb{jOQ!a zSk62i%bUlOa_3ele;$#Sz-_#YnS;}FybNw(WiU&j3}%(ekZi0B9*>p5<4I+3t5gP$ z$je|h-iN8K=E65q_-3W{%^%!9FJ&*;SoX}OV%al`TFRbVrR;e`o;|Zk*>$cdd{gY3 zNu`>F?oG0_2j^y$JLl$R4KHDLEG_%bkU&nNmkXsiRX$wb+o-usZHA oEoo9oc&3p%Z0Aa30|Q0^?rl8JTQ+!Me?NJME?jfJ>_+nc0Ip!~`2YX_ literal 0 HcmV?d00001 diff --git a/public/fonts/Roboto-Bold.ttf b/public/fonts/Roboto-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..925694f02da954607dce29076dbc08d2eb800fcd GIT binary patch literal 42708 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 literal 0 HcmV?d00001 diff --git a/schemas/early_player_emails.md b/schemas/early_player_emails.md new file mode 100644 index 0000000..e48460e --- /dev/null +++ b/schemas/early_player_emails.md @@ -0,0 +1,13 @@ +create table public.early_player_emails ( + id bigint generated by default as identity not null, + created_at timestamp with time zone not null default now(), + email text not null, + preset text not null default 'founder-card-5', + constraint early_player_emails_pkey primary key (id), + constraint early_player_emails_email_key unique (email), + constraint early_player_emails_email_len check (char_length(email) between 3 and 254), + constraint early_player_emails_preset_len check (char_length(preset) between 1 and 80) +); + +-- Row `id` is the founder card number stamped onto the PNG. +-- Access is service-role only (RLS on, no policies; anon/authenticated revoked). diff --git a/src/app/api/download/[jobId]/route.ts b/src/app/api/download/[jobId]/route.ts new file mode 100644 index 0000000..8afe309 --- /dev/null +++ b/src/app/api/download/[jobId]/route.ts @@ -0,0 +1,48 @@ +import { createReadStream } from "node:fs"; +import { stat } from "node:fs/promises"; +import { Readable } from "node:stream"; +import { getSessionAccount } from "@/lib/auth/require-session"; +import { canReadPage } from "@/lib/auth/permissions"; +import { isValidJobId, jobPaths, sweepExpiredJobs } from "@/lib/card-gen/jobs"; + +export const runtime = "nodejs"; +export const dynamic = "force-dynamic"; + +export async function GET( + _request: Request, + context: { params: Promise<{ jobId: string }> }, +) { + const account = await getSessionAccount(); + if (!account || !canReadPage(account, "founders-card")) { + return Response.json({ error: "Unauthorized" }, { status: 401 }); + } + + const { jobId } = await context.params; + if (!isValidJobId(jobId)) { + return Response.json({ error: "Not found" }, { status: 404 }); + } + + await sweepExpiredJobs(); + const { zipPath } = jobPaths(jobId); + let size = 0; + try { + const st = await stat(zipPath); + size = st.size; + } catch { + return Response.json({ error: "Not found" }, { status: 404 }); + } + if (!size) { + return Response.json({ error: "Not found" }, { status: 404 }); + } + + const nodeStream = createReadStream(zipPath); + const webStream = Readable.toWeb(nodeStream) as ReadableStream; + return new Response(webStream, { + headers: { + "Content-Type": "application/zip", + "Content-Length": String(size), + "Content-Disposition": 'attachment; filename="ids.zip"', + "Cache-Control": "no-store", + }, + }); +} diff --git a/src/app/api/founders-card/presets/[presetId]/font/route.ts b/src/app/api/founders-card/presets/[presetId]/font/route.ts new file mode 100644 index 0000000..5652229 --- /dev/null +++ b/src/app/api/founders-card/presets/[presetId]/font/route.ts @@ -0,0 +1,46 @@ +import { createReadStream } from "node:fs"; +import { stat } from "node:fs/promises"; +import { Readable } from "node:stream"; +import { getSessionAccount } from "@/lib/auth/require-session"; +import { canReadPage } from "@/lib/auth/permissions"; +import { getLoadedPreset, isPresetId } from "@/lib/card-gen/preset-store"; + +export const runtime = "nodejs"; +export const dynamic = "force-dynamic"; + +export async function GET( + _request: Request, + context: { params: Promise<{ presetId: string }> }, +) { + const account = await getSessionAccount(); + if (!account || !canReadPage(account, "founders-card")) { + return Response.json({ error: "Unauthorized" }, { status: 401 }); + } + const { presetId } = await context.params; + if (!isPresetId(presetId)) { + return Response.json({ error: "Not found" }, { status: 404 }); + } + const preset = await getLoadedPreset(presetId); + if (!preset?.fontPath) { + return Response.json({ error: "Not found" }, { status: 404 }); + } + let size = 0; + try { + size = (await stat(preset.fontPath)).size; + } catch { + return Response.json({ error: "Not found" }, { status: 404 }); + } + if (!size) return Response.json({ error: "Not found" }, { status: 404 }); + const stream = Readable.toWeb( + createReadStream(preset.fontPath), + ) as ReadableStream; + const name = (preset.fontName ?? "custom.ttf").replace(/"/g, ""); + return new Response(stream, { + headers: { + "Content-Type": "application/octet-stream", + "Content-Length": String(size), + "Content-Disposition": `attachment; filename="${name}"`, + "Cache-Control": "no-store", + }, + }); +} diff --git a/src/app/api/founders-card/presets/[presetId]/image/route.ts b/src/app/api/founders-card/presets/[presetId]/image/route.ts new file mode 100644 index 0000000..cf78341 --- /dev/null +++ b/src/app/api/founders-card/presets/[presetId]/image/route.ts @@ -0,0 +1,50 @@ +import { createReadStream } from "node:fs"; +import { stat } from "node:fs/promises"; +import { Readable } from "node:stream"; +import { getSessionAccount } from "@/lib/auth/require-session"; +import { canReadPage } from "@/lib/auth/permissions"; +import { getLoadedPreset, isPresetId } from "@/lib/card-gen/preset-store"; + +export const runtime = "nodejs"; +export const dynamic = "force-dynamic"; + +export async function GET( + _request: Request, + context: { params: Promise<{ presetId: string }> }, +) { + const account = await getSessionAccount(); + if (!account || !canReadPage(account, "founders-card")) { + return Response.json({ error: "Unauthorized" }, { status: 401 }); + } + const { presetId } = await context.params; + if (!isPresetId(presetId)) { + return Response.json({ error: "Not found" }, { status: 404 }); + } + const preset = await getLoadedPreset(presetId); + if (!preset) return Response.json({ error: "Not found" }, { status: 404 }); + let size = 0; + try { + size = (await stat(preset.imagePath)).size; + } catch { + return Response.json({ error: "Not found" }, { status: 404 }); + } + if (!size) return Response.json({ error: "Not found" }, { status: 404 }); + const stream = Readable.toWeb( + createReadStream(preset.imagePath), + ) as ReadableStream; + const ext = preset.imageFile.split(".").pop()?.toLowerCase() ?? "png"; + const type = + ext === "jpg" || ext === "jpeg" + ? "image/jpeg" + : ext === "webp" + ? "image/webp" + : "image/png"; + return new Response(stream, { + headers: { + "Content-Type": type, + "Content-Length": String(size), + "Content-Disposition": `inline; filename="${preset.imageName.replace(/"/g, "")}"`, + "Cache-Control": "no-store", + }, + }); +} diff --git a/src/app/api/founders-card/presets/[presetId]/route.ts b/src/app/api/founders-card/presets/[presetId]/route.ts new file mode 100644 index 0000000..a8c69dd --- /dev/null +++ b/src/app/api/founders-card/presets/[presetId]/route.ts @@ -0,0 +1,26 @@ +import { getSessionAccount } from "@/lib/auth/require-session"; +import { canWritePage } from "@/lib/auth/permissions"; +import { + deleteStoredPreset, + isPresetId, +} from "@/lib/card-gen/preset-store"; + +export const runtime = "nodejs"; +export const dynamic = "force-dynamic"; + +export async function DELETE( + _request: Request, + context: { params: Promise<{ presetId: string }> }, +) { + const account = await getSessionAccount(); + if (!account || !canWritePage(account, "founders-card")) { + return Response.json({ error: "Unauthorized" }, { status: 401 }); + } + const { presetId } = await context.params; + if (!isPresetId(presetId)) { + return Response.json({ error: "Not found" }, { status: 404 }); + } + const ok = await deleteStoredPreset(presetId); + if (!ok) return Response.json({ error: "Not found" }, { status: 404 }); + return Response.json({ ok: true }); +} diff --git a/src/app/api/founders-card/presets/route.ts b/src/app/api/founders-card/presets/route.ts new file mode 100644 index 0000000..a884fd6 --- /dev/null +++ b/src/app/api/founders-card/presets/route.ts @@ -0,0 +1,142 @@ +import { getSessionAccount } from "@/lib/auth/require-session"; +import { canReadPage, canWritePage } from "@/lib/auth/permissions"; +import { + CUSTOM_FONT_FAMILY, + isFontFile, + isImageFile, + LIMITS, + parseGenerateConfig, +} from "@/lib/card-gen/id-config"; +import { PRESET_FONT_FAMILIES } from "@/lib/card-gen/fonts"; +import { + listPresetMeta, + saveStoredPreset, + type PresetMeta, +} from "@/lib/card-gen/preset-store"; + +export const runtime = "nodejs"; +export const dynamic = "force-dynamic"; + +function jsonError(message: string, status: number) { + return Response.json({ error: message }, { status }); +} + +function toPublicMeta(meta: PresetMeta) { + return { + id: meta.id, + name: meta.name, + config: meta.config, + imageName: meta.imageName, + hasImage: Boolean(meta.imageFile), + fontName: meta.fontName, + hasFont: Boolean(meta.fontFile), + createdAt: meta.createdAt, + updatedAt: meta.updatedAt, + }; +} + +async function fileBytes( + file: File, +): Promise<{ bytes: Buffer; name: string; type: string }> { + return { + bytes: Buffer.from(await file.arrayBuffer()), + name: file.name, + type: file.type, + }; +} + +export async function GET() { + const account = await getSessionAccount(); + if (!account || !canReadPage(account, "founders-card")) { + return jsonError("Unauthorized", 401); + } + const presets = await listPresetMeta(); + return Response.json({ presets: presets.map(toPublicMeta) }); +} + +export async function POST(request: Request) { + const account = await getSessionAccount(); + if (!account || !canWritePage(account, "founders-card")) { + return jsonError("Unauthorized", 401); + } + + let form: FormData; + try { + form = await request.formData(); + } catch { + return jsonError("Invalid multipart body", 400); + } + + const name = String(form.get("name") ?? "").trim(); + if (!name) return jsonError("Preset name is required", 400); + + const idRaw = String(form.get("id") ?? "").trim(); + const id = idRaw || undefined; + + const configRaw = form.get("config"); + if (typeof configRaw !== "string") return jsonError("Config is required", 400); + let parsedJson: unknown; + try { + parsedJson = JSON.parse(configRaw); + } catch { + return jsonError("Config must be JSON", 400); + } + const config = parseGenerateConfig(parsedJson); + if (!config) return jsonError("Invalid config", 400); + if ( + config.fontFamily !== CUSTOM_FONT_FAMILY && + !PRESET_FONT_FAMILIES.includes(config.fontFamily) + ) { + return jsonError("Unknown font family", 400); + } + + const image = form.get("image"); + let imageInput: { bytes: Buffer; name: string; type: string } | null = null; + if (image instanceof File && image.size > 0) { + if (image.size > LIMITS.imageBytes) { + return jsonError("Image must be 10MB or smaller", 400); + } + if (!isImageFile(image)) { + return jsonError("Image must be PNG, JPG, or WebP", 400); + } + imageInput = await fileBytes(image); + } + + const font = form.get("font"); + let fontInput: { bytes: Buffer; name: string; type: string } | null = null; + if (font instanceof File && font.size > 0) { + if (font.size > LIMITS.fontBytes) { + return jsonError("Font must be 5MB or smaller", 400); + } + if (!isFontFile(font)) return jsonError("Font must be TTF or OTF", 400); + fontInput = await fileBytes(font); + } + + if (config.fontFamily === CUSTOM_FONT_FAMILY && !fontInput) { + const clearFont = String(form.get("clearFont") ?? "") === "1"; + if (clearFont && !id) { + return jsonError("Custom font file is required", 400); + } + } + + try { + const saved = await saveStoredPreset({ + id, + name, + config, + image: imageInput, + font: fontInput, + clearFont: !fontInput && String(form.get("clearFont") ?? "") === "1", + }); + return Response.json(toPublicMeta(saved)); + } catch (err) { + const message = err instanceof Error ? err.message : "Could not save preset"; + const status = + message === "A preset with that name already exists" || + message === "Image is required" || + message === "Preset name is required" + ? 400 + : 500; + return jsonError(message, status); + } +} diff --git a/src/app/api/founders-card/route.ts b/src/app/api/founders-card/route.ts new file mode 100644 index 0000000..60a011d --- /dev/null +++ b/src/app/api/founders-card/route.ts @@ -0,0 +1,48 @@ +import { getClientIp } from "@/lib/auth/client-ip"; +import { FOUNDERS_CARD_CORS, foundersCardJsonError } from "@/lib/card-gen/cors"; +import { checkPublicCardRateLimit } from "@/lib/card-gen/public-rate-limit"; +import { pngResponse, renderFoundersCardPng } from "@/lib/card-gen/render-public"; + +export const runtime = "nodejs"; +export const maxDuration = 60; +export const dynamic = "force-dynamic"; + +export async function OPTIONS() { + return new Response(null, { status: 204, headers: FOUNDERS_CARD_CORS }); +} + +export async function GET(request: Request) { + const ip = getClientIp(request); + const rate = checkPublicCardRateLimit(ip); + if (!rate.allowed) { + return Response.json( + { error: "Too many requests. Try again later." }, + { + status: 429, + headers: { + ...FOUNDERS_CARD_CORS, + "Retry-After": String(rate.retryAfterSeconds), + "Cache-Control": "no-store", + }, + }, + ); + } + + const url = new URL(request.url); + const presetName = url.searchParams.get("preset")?.trim() ?? ""; + const idRaw = url.searchParams.get("id")?.trim() ?? ""; + if (!presetName) return foundersCardJsonError("preset is required", 400); + if (!idRaw) return foundersCardJsonError("id is required", 400); + if (!/^\d+$/.test(idRaw)) return foundersCardJsonError("id must be a number", 400); + + const rendered = await renderFoundersCardPng(presetName, Number(idRaw)); + if (!rendered.ok) { + return foundersCardJsonError(rendered.error, rendered.status); + } + + return pngResponse(rendered.png, rendered.filename, { + ...FOUNDERS_CARD_CORS, + "Cache-Control": "public, max-age=60", + "X-Founder-Id": String(Number(idRaw)), + }); +} diff --git a/src/app/api/founders-card/signup/route.ts b/src/app/api/founders-card/signup/route.ts new file mode 100644 index 0000000..73c6fde --- /dev/null +++ b/src/app/api/founders-card/signup/route.ts @@ -0,0 +1,99 @@ +import { getClientIp } from "@/lib/auth/client-ip"; +import { FOUNDERS_CARD_CORS, foundersCardJsonError } from "@/lib/card-gen/cors"; +import { + normalizeSignupEmail, + upsertEarlyPlayerEmail, +} from "@/lib/card-gen/early-player-emails"; +import { checkPublicSignupRateLimit } from "@/lib/card-gen/public-rate-limit"; +import { + DEFAULT_SIGNUP_PRESET, + pngResponse, + renderFoundersCardPng, +} from "@/lib/card-gen/render-public"; + +export const runtime = "nodejs"; +export const maxDuration = 60; +export const dynamic = "force-dynamic"; + +export async function OPTIONS() { + return new Response(null, { status: 204, headers: FOUNDERS_CARD_CORS }); +} + +async function readBody( + request: Request, +): Promise<{ email: string; preset: string }> { + const contentType = request.headers.get("content-type") ?? ""; + if (contentType.includes("application/json")) { + const body = (await request.json()) as { + email?: unknown; + preset?: unknown; + }; + return { + email: typeof body.email === "string" ? body.email : "", + preset: typeof body.preset === "string" ? body.preset : "", + }; + } + const form = await request.formData(); + return { + email: String(form.get("email") ?? ""), + preset: String(form.get("preset") ?? ""), + }; +} + +export async function POST(request: Request) { + const ip = getClientIp(request); + const rate = checkPublicSignupRateLimit(ip); + if (!rate.allowed) { + return Response.json( + { error: "Too many requests. Try again later." }, + { + status: 429, + headers: { + ...FOUNDERS_CARD_CORS, + "Retry-After": String(rate.retryAfterSeconds), + "Cache-Control": "no-store", + }, + }, + ); + } + + let emailRaw = ""; + let presetRaw = ""; + try { + const body = await readBody(request); + emailRaw = body.email; + presetRaw = body.preset; + } catch { + return foundersCardJsonError("Invalid request body", 400); + } + + const email = normalizeSignupEmail(emailRaw); + if (!email) return foundersCardJsonError("A valid email is required", 400); + + const preset = (presetRaw.trim() || DEFAULT_SIGNUP_PRESET).slice(0, 80); + + const saved = await upsertEarlyPlayerEmail(email, preset); + if ("error" in saved) { + return foundersCardJsonError(saved.error, saved.status); + } + + const rendered = await renderFoundersCardPng(preset, saved.id); + if (!rendered.ok) { + return Response.json( + { error: rendered.error, id: saved.id }, + { + status: rendered.status, + headers: { + ...FOUNDERS_CARD_CORS, + "Cache-Control": "no-store", + "X-Founder-Id": String(saved.id), + }, + }, + ); + } + + return pngResponse(rendered.png, rendered.filename, { + ...FOUNDERS_CARD_CORS, + "X-Founder-Id": String(saved.id), + }); +} diff --git a/src/app/api/founders-card/signups/route.ts b/src/app/api/founders-card/signups/route.ts new file mode 100644 index 0000000..35f18e8 --- /dev/null +++ b/src/app/api/founders-card/signups/route.ts @@ -0,0 +1,20 @@ +import { getSessionAccount } from "@/lib/auth/require-session"; +import { canReadPage } from "@/lib/auth/permissions"; +import { listEarlyPlayerEmails } from "@/lib/card-gen/early-player-emails"; + +export const runtime = "nodejs"; +export const dynamic = "force-dynamic"; + +export async function GET() { + const account = await getSessionAccount(); + if (!account || !canReadPage(account, "founders-card")) { + return Response.json({ error: "Unauthorized" }, { status: 401 }); + } + + const result = await listEarlyPlayerEmails(); + if ("error" in result) { + return Response.json({ error: result.error }, { status: 500 }); + } + + return Response.json({ emails: result.rows }); +} diff --git a/src/app/api/generate/route.ts b/src/app/api/generate/route.ts new file mode 100644 index 0000000..723440f --- /dev/null +++ b/src/app/api/generate/route.ts @@ -0,0 +1,169 @@ +import { writeFile } from "node:fs/promises"; +import path from "node:path"; +import { createZipFromDir } from "@/lib/card-gen/create-zip"; +import { extFromFile } from "@/lib/card-gen/file-ext"; +import { + CUSTOM_FONT_FAMILY, + formatId, + isFontFile, + isImageFile, + LIMITS, + parseGenerateConfig, + pickDrawStyle, + sanitizeFilename, +} from "@/lib/card-gen/id-config"; +import { fontEntriesForFamily } from "@/lib/card-gen/font-files"; +import { PRESET_FONT_FAMILIES } from "@/lib/card-gen/fonts"; +import { generatePngsInWorkers } from "@/lib/card-gen/generate-pool"; +import { createJobDir } from "@/lib/card-gen/jobs"; +import { getSessionAccount } from "@/lib/auth/require-session"; +import { canWritePage } from "@/lib/auth/permissions"; + +export const runtime = "nodejs"; +export const maxDuration = 300; +export const dynamic = "force-dynamic"; + +function jsonError(message: string, status: number) { + return Response.json({ error: message }, { status }); +} + +export async function POST(request: Request) { + const account = await getSessionAccount(); + if (!account || !canWritePage(account, "founders-card")) { + return jsonError("Unauthorized", 401); + } + + let form: FormData; + try { + form = await request.formData(); + } catch { + return jsonError("Invalid multipart body", 400); + } + + const image = form.get("image"); + if (!(image instanceof File) || image.size === 0) { + return jsonError("Image is required", 400); + } + if (image.size > LIMITS.imageBytes) { + return jsonError("Image must be 10MB or smaller", 400); + } + if (!isImageFile(image)) { + return jsonError("Image must be PNG, JPG, or WebP", 400); + } + + const configRaw = form.get("config"); + if (typeof configRaw !== "string") { + return jsonError("Config is required", 400); + } + let parsedJson: unknown; + try { + parsedJson = JSON.parse(configRaw); + } catch { + return jsonError("Config must be JSON", 400); + } + const config = parseGenerateConfig(parsedJson); + if (!config) { + return jsonError("Invalid config", 400); + } + + const font = form.get("font"); + let fontFile: File | null = null; + if (font instanceof File && font.size > 0) { + if (font.size > LIMITS.fontBytes) { + return jsonError("Font must be 5MB or smaller", 400); + } + if (!isFontFile(font)) { + return jsonError("Font must be TTF or OTF", 400); + } + fontFile = font; + } + + if (config.fontFamily === CUSTOM_FONT_FAMILY && !fontFile) { + return jsonError("Custom font file is required", 400); + } + if ( + config.fontFamily !== CUSTOM_FONT_FAMILY && + !PRESET_FONT_FAMILIES.includes(config.fontFamily) + ) { + return jsonError("Unknown font family", 400); + } + + const encoder = new TextEncoder(); + const stream = new ReadableStream({ + async start(controller) { + const send = (obj: unknown) => { + controller.enqueue(encoder.encode(`${JSON.stringify(obj)}\n`)); + }; + try { + const job = await createJobDir(); + const imagePath = path.join( + job.dir, + `base${extFromFile(image, ".png")}`, + ); + await writeFile(imagePath, Buffer.from(await image.arrayBuffer())); + + let customFontPath: string | null = null; + if (fontFile) { + customFontPath = path.join( + job.dir, + `custom${extFromFile(fontFile, ".ttf")}`, + ); + await writeFile( + customFontPath, + Buffer.from(await fontFile.arrayBuffer()), + ); + } + + const fonts = fontEntriesForFamily(config.fontFamily, customFontPath); + if (fonts.length === 0) { + send({ phase: "error", message: "Could not resolve fonts" }); + controller.close(); + return; + } + + const tasks = []; + for (let i = 0; i < config.count; i += 1) { + const n = config.start + i; + const text = formatId(config.prefix, n, config.pad, config.suffix); + const name = `${sanitizeFilename(text)}.png`; + tasks.push({ + text, + outPath: path.join(job.pngDir, name), + }); + } + + send({ phase: "generate", current: 0, total: tasks.length }); + await generatePngsInWorkers({ + imagePath, + fonts, + style: pickDrawStyle(config), + tasks, + onProgress: (current, total) => { + send({ phase: "generate", current, total }); + }, + }); + + send({ phase: "zip", current: 0, total: tasks.length }); + await createZipFromDir(job.pngDir, job.zipPath, (current, total) => { + send({ phase: "zip", current, total }); + }); + + send({ phase: "done", id: job.id }); + controller.close(); + } catch (err) { + const message = + err instanceof Error ? err.message : "Generate failed"; + send({ phase: "error", message }); + controller.close(); + } + }, + }); + + return new Response(stream, { + headers: { + "Content-Type": "application/x-ndjson", + "Cache-Control": "no-store", + "X-Accel-Buffering": "no", + }, + }); +} diff --git a/src/app/founders-card-design/early-emails-list.tsx b/src/app/founders-card-design/early-emails-list.tsx new file mode 100644 index 0000000..75576e3 --- /dev/null +++ b/src/app/founders-card-design/early-emails-list.tsx @@ -0,0 +1,159 @@ +"use client"; + +import { useCallback, useMemo, useState } from "react"; +import type { EarlyPlayerEmailRow } from "@/lib/card-gen/early-player-emails"; + +type Props = { + initialEmails: EarlyPlayerEmailRow[]; + initialError: string | null; + onSelectId?: (id: number) => void; +}; + +const inputClass = + "w-full rounded-md border border-zinc-300 bg-white px-3 py-1.5 text-sm text-zinc-900 shadow-sm focus:border-sky-500 focus:outline-none focus:ring-1 focus:ring-sky-500 dark:border-zinc-600 dark:bg-zinc-950 dark:text-zinc-100"; + +function utcStamp(iso: string): string { + const d = new Date(iso); + if (Number.isNaN(d.getTime())) return iso; + return d.toISOString().replace("T", " ").slice(0, 16) + " UTC"; +} + +export function EarlyEmailsList({ + initialEmails, + initialError, + onSelectId, +}: Props) { + const [emails, setEmails] = useState(initialEmails); + const [error, setError] = useState(initialError); + const [query, setQuery] = useState(""); + const [loading, setLoading] = useState(false); + + const refresh = useCallback(async () => { + setLoading(true); + try { + const res = await fetch("/api/founders-card/signups", { + cache: "no-store", + }); + const body = (await res.json().catch(() => null)) as + | { emails?: EarlyPlayerEmailRow[]; error?: string } + | null; + if (!res.ok) { + throw new Error(body?.error || `Could not load emails (${res.status})`); + } + setEmails(Array.isArray(body?.emails) ? body.emails : []); + setError(null); + } catch (err) { + setError(err instanceof Error ? err.message : "Could not load emails"); + } finally { + setLoading(false); + } + }, []); + + const filtered = useMemo(() => { + const q = query.trim().toLowerCase(); + if (!q) return emails; + return emails.filter((row) => { + return ( + String(row.id).includes(q) || + row.email.toLowerCase().includes(q) || + row.preset.toLowerCase().includes(q) + ); + }); + }, [emails, query]); + + return ( +

+ ); +} diff --git a/src/app/founders-card-design/editor.tsx b/src/app/founders-card-design/editor.tsx new file mode 100644 index 0000000..961ac6a --- /dev/null +++ b/src/app/founders-card-design/editor.tsx @@ -0,0 +1,1135 @@ +"use client"; + +import Link from "next/link"; +import { + useCallback, + useEffect, + useMemo, + useRef, + useState, + type ChangeEvent, + type DragEvent, + type PointerEvent as ReactPointerEvent, +} from "react"; +import { drawIdText, type TextMetricsBox } from "@/lib/card-gen/draw-id"; +import { PRESET_FONT_FAMILIES } from "@/lib/card-gen/fonts"; +import { + CUSTOM_FONT_FAMILY, + DEFAULT_CONFIG, + isFontFile, + isImageFile, + LIMITS, + sampleId, + type GenerateConfig, + type TextAlign, +} from "@/lib/card-gen/id-config"; +import { + deletePreset, + listPresets, + loadDraft, + saveDraft, + savePreset, + type CardPreset, +} from "@/lib/card-gen/local-store"; +import { + cacheServerPresetsLocally, + deleteServerPreset, + fetchServerPresets, + pushPresetToServer, +} from "@/lib/card-gen/preset-api"; +import { + isProgressEvent, + type GenerateProgressEvent, +} from "@/lib/card-gen/progress"; +import type { EarlyPlayerEmailRow } from "@/lib/card-gen/early-player-emails"; +import { EarlyEmailsList } from "./early-emails-list"; + +type Props = { + canGenerate: boolean; + earlyEmails: EarlyPlayerEmailRow[]; + earlyEmailsError: string | null; +}; + +type BusyState = + | { kind: "idle" } + | { kind: "generate"; current: number; total: number } + | { kind: "zip"; current: number; total: number }; + +function clamp(n: number, min: number, max: number): number { + return Math.min(max, Math.max(min, n)); +} + +function eventToPercent( + clientX: number, + clientY: number, + canvas: HTMLCanvasElement, +): { xPercent: number; yPercent: number } { + const rect = canvas.getBoundingClientRect(); + const x = ((clientX - rect.left) / rect.width) * canvas.width; + const y = ((clientY - rect.top) / rect.height) * canvas.height; + return { + xPercent: clamp((x / canvas.width) * 100, 0, 100), + yPercent: clamp((y / canvas.height) * 100, 0, 100), + }; +} + +function hitBox( + clientX: number, + clientY: number, + canvas: HTMLCanvasElement, + box: TextMetricsBox | null, +): boolean { + if (!box) return false; + const rect = canvas.getBoundingClientRect(); + const x = ((clientX - rect.left) / rect.width) * canvas.width; + const y = ((clientY - rect.top) / rect.height) * canvas.height; + const pad = 12; + return ( + x >= box.x - pad && + x <= box.x + box.width + pad && + y >= box.y - pad && + y <= box.y + box.height + pad + ); +} + +async function readNdjson( + response: Response, + onEvent: (ev: GenerateProgressEvent) => void, +): Promise { + if (!response.body) throw new Error("No response body"); + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + let buf = ""; + while (true) { + const { done, value } = await reader.read(); + if (done) break; + buf += decoder.decode(value, { stream: true }); + let nl = buf.indexOf("\n"); + while (nl >= 0) { + const line = buf.slice(0, nl).trim(); + buf = buf.slice(nl + 1); + if (line) { + const parsed: unknown = JSON.parse(line); + if (isProgressEvent(parsed)) onEvent(parsed); + } + nl = buf.indexOf("\n"); + } + } + const tail = buf.trim(); + if (tail) { + const parsed: unknown = JSON.parse(tail); + if (isProgressEvent(parsed)) onEvent(parsed); + } +} + +function Field({ + label, + htmlFor, + children, +}: { + label: string; + htmlFor?: string; + children: React.ReactNode; +}) { + return ( + + ); +} + +const inputClass = + "w-full rounded-md border border-zinc-300 bg-white px-3 py-1.5 text-sm text-zinc-900 shadow-sm focus:border-sky-500 focus:outline-none focus:ring-1 focus:ring-sky-500 dark:border-zinc-600 dark:bg-zinc-950 dark:text-zinc-100"; +const checkClass = + "size-4 rounded border-zinc-300 text-zinc-900 focus:ring-zinc-400 dark:border-zinc-600"; + +export function FoundersCardEditor({ + canGenerate, + earlyEmails, + earlyEmailsError, +}: Props) { + const canvasRef = useRef(null); + const imageRef = useRef(null); + const boxRef = useRef(null); + const customFaceRef = useRef(null); + const customUrlRef = useRef(null); + const imageUrlRef = useRef(null); + const dragModeRef = useRef<"none" | "move" | "place">("none"); + const saveTimerRef = useRef(null); + + const [ready, setReady] = useState(false); + const [config, setConfig] = useState(DEFAULT_CONFIG); + const [imageFile, setImageFile] = useState(null); + const [fontFile, setFontFile] = useState(null); + const [imageLoaded, setImageLoaded] = useState(false); + const [fontReadyTick, setFontReadyTick] = useState(0); + const [presets, setPresets] = useState([]); + const [activePresetId, setActivePresetId] = useState(null); + const [presetName, setPresetName] = useState(""); + const [savedAt, setSavedAt] = useState(null); + const [saveError, setSaveError] = useState(null); + const [dropActive, setDropActive] = useState(false); + const [busy, setBusy] = useState({ kind: "idle" }); + const [downloadHref, setDownloadHref] = useState(null); + const [error, setError] = useState(null); + + const patch = useCallback((partial: Partial) => { + setConfig((prev) => ({ ...prev, ...partial })); + }, []); + + const takeImage = useCallback((file: File | null) => { + if (!file) { + setImageFile(null); + setImageLoaded(false); + return; + } + if (!isImageFile(file)) { + setError("Image must be PNG, JPG, or WebP"); + return; + } + if (file.size > LIMITS.imageBytes) { + setError("Image must be 10MB or smaller"); + return; + } + setError(null); + setImageFile(file); + setImageLoaded(false); + }, []); + + const takeFont = useCallback((file: File | null) => { + if (!file) { + setFontFile(null); + patch({ fontFamily: "Inter" }); + return; + } + if (!isFontFile(file)) { + setError("Font must be TTF or OTF"); + return; + } + if (file.size > LIMITS.fontBytes) { + setError("Font must be 5MB or smaller"); + return; + } + setError(null); + setFontFile(file); + patch({ fontFamily: CUSTOM_FONT_FAMILY }); + }, [patch]); + + useEffect(() => { + let cancelled = false; + void (async () => { + try { + const [draft, stored] = await Promise.all([loadDraft(), listPresets()]); + if (cancelled) return; + let presets = stored; + try { + const remote = await fetchServerPresets(); + if (cancelled) return; + if (remote.length > 0) { + await cacheServerPresetsLocally(remote); + const byId = new Map(stored.map((p) => [p.id, p])); + for (const p of remote) byId.set(p.id, p); + presets = [...byId.values()].sort( + (a, b) => a.createdAt - b.createdAt, + ); + } + } catch { + // Keep locally cached presets if the server is unreachable. + } + if (cancelled) return; + setConfig(draft.config); + setImageFile(draft.image); + setFontFile(draft.font); + setActivePresetId(draft.activePresetId); + setSavedAt(draft.savedAt || null); + setPresets(presets); + const active = presets.find((p) => p.id === draft.activePresetId); + if (active) setPresetName(active.name); + } catch (err) { + if (!cancelled) { + setSaveError( + err instanceof Error ? err.message : "Could not load saved config", + ); + } + } finally { + if (!cancelled) setReady(true); + } + })(); + return () => { + cancelled = true; + }; + }, []); + + useEffect(() => { + if (!ready) return; + if (saveTimerRef.current) window.clearTimeout(saveTimerRef.current); + saveTimerRef.current = window.setTimeout(() => { + void (async () => { + try { + const at = await saveDraft({ + config, + image: imageFile, + font: fontFile, + activePresetId, + }); + setSavedAt(at); + setSaveError(null); + } catch (err) { + setSaveError( + err instanceof Error ? err.message : "Could not save locally", + ); + } + })(); + }, 250); + return () => { + if (saveTimerRef.current) window.clearTimeout(saveTimerRef.current); + }; + }, [ready, config, imageFile, fontFile, activePresetId]); + + useEffect(() => { + if (imageUrlRef.current) { + URL.revokeObjectURL(imageUrlRef.current); + imageUrlRef.current = null; + } + imageRef.current = null; + setImageLoaded(false); + if (!imageFile) { + return; + } + const url = URL.createObjectURL(imageFile); + imageUrlRef.current = url; + const img = new Image(); + img.onload = () => { + imageRef.current = img; + setImageLoaded(true); + }; + img.onerror = () => { + setError("Could not read the base image"); + imageRef.current = null; + }; + img.src = url; + return () => { + if (imageUrlRef.current) { + URL.revokeObjectURL(imageUrlRef.current); + imageUrlRef.current = null; + } + }; + }, [imageFile]); + + useEffect(() => { + let cancelled = false; + const prevFace = customFaceRef.current; + const prevUrl = customUrlRef.current; + if (prevFace) { + document.fonts.delete(prevFace); + customFaceRef.current = null; + } + if (prevUrl) { + URL.revokeObjectURL(prevUrl); + customUrlRef.current = null; + } + if (!fontFile) { + setFontReadyTick((n) => n + 1); + return; + } + const url = URL.createObjectURL(fontFile); + customUrlRef.current = url; + const face = new FontFace(CUSTOM_FONT_FAMILY, `url(${url})`); + customFaceRef.current = face; + void face + .load() + .then((loaded) => { + if (cancelled) return; + document.fonts.add(loaded); + setFontReadyTick((n) => n + 1); + }) + .catch(() => { + if (!cancelled) setError("Could not load the custom font"); + }); + return () => { + cancelled = true; + }; + }, [fontFile]); + + const text = useMemo(() => sampleId(config), [config]); + + const redraw = useCallback(() => { + const canvas = canvasRef.current; + const img = imageRef.current; + if (!canvas || !img) return; + const ctx = canvas.getContext("2d"); + if (!ctx) return; + canvas.width = img.naturalWidth; + canvas.height = img.naturalHeight; + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(img, 0, 0); + const box = drawIdText(ctx, text, canvas.width, canvas.height, config); + boxRef.current = box; + ctx.save(); + ctx.setLineDash([6, 4]); + ctx.strokeStyle = "rgba(14, 165, 233, 0.95)"; + ctx.lineWidth = Math.max(1, canvas.width / 500); + ctx.strokeRect(box.x - 6, box.y - 6, box.width + 12, box.height + 12); + ctx.restore(); + }, [config, text]); + + useEffect(() => { + if (!imageLoaded) return; + void document.fonts.ready.then(() => redraw()); + }, [redraw, imageLoaded, fontReadyTick]); + + const onPointerDown = (e: ReactPointerEvent) => { + const canvas = canvasRef.current; + if (!canvas) return; + canvas.setPointerCapture(e.pointerId); + if (hitBox(e.clientX, e.clientY, canvas, boxRef.current)) { + dragModeRef.current = "move"; + } else { + dragModeRef.current = "place"; + const p = eventToPercent(e.clientX, e.clientY, canvas); + patch({ xPercent: p.xPercent, yPercent: p.yPercent }); + } + }; + + const onPointerMove = (e: ReactPointerEvent) => { + if (dragModeRef.current === "none") return; + const canvas = canvasRef.current; + if (!canvas) return; + const p = eventToPercent(e.clientX, e.clientY, canvas); + patch({ xPercent: p.xPercent, yPercent: p.yPercent }); + }; + + const onPointerUp = (e: ReactPointerEvent) => { + dragModeRef.current = "none"; + const canvas = canvasRef.current; + if (canvas?.hasPointerCapture(e.pointerId)) { + canvas.releasePointerCapture(e.pointerId); + } + }; + + const onDropFile = (e: DragEvent) => { + e.preventDefault(); + setDropActive(false); + const file = e.dataTransfer.files[0]; + if (!file) return; + if (isFontFile(file)) takeFont(file); + else takeImage(file); + }; + + const onImageInput = (e: ChangeEvent) => { + takeImage(e.target.files?.[0] ?? null); + e.target.value = ""; + }; + + const onFontInput = (e: ChangeEvent) => { + const file = e.target.files?.[0] ?? null; + if (file) takeFont(file); + e.target.value = ""; + }; + + const applyPreset = (preset: CardPreset) => { + setConfig(preset.config); + setImageFile(preset.image); + setFontFile(preset.font); + setActivePresetId(preset.id); + setPresetName(preset.name); + setDownloadHref(null); + }; + + const onSavePreset = async (asNew: boolean) => { + const name = presetName.trim(); + if (!name) { + setError("Name the preset first"); + return; + } + if (canGenerate && !imageFile) { + setError("Select a base photo before publishing a preset"); + return; + } + try { + let id = asNew ? undefined : (activePresetId ?? undefined); + if (canGenerate) { + const remote = await pushPresetToServer({ + id, + name, + config, + image: imageFile, + font: fontFile, + }); + id = remote.id; + } + const saved = await savePreset({ + id, + name, + config, + image: imageFile, + font: fontFile, + }); + const next = await listPresets(); + setPresets(next); + setActivePresetId(saved.id); + setPresetName(saved.name); + setError(null); + } catch (err) { + setError(err instanceof Error ? err.message : "Could not save preset"); + } + }; + + const onDeletePreset = async () => { + if (!activePresetId) return; + try { + if (canGenerate) { + await deleteServerPreset(activePresetId); + } + await deletePreset(activePresetId); + const next = await listPresets(); + setPresets(next); + setActivePresetId(null); + } catch (err) { + setError(err instanceof Error ? err.message : "Could not delete preset"); + } + }; + + const generate = async () => { + if (!canGenerate) return; + if (!imageFile) { + setError("Select a base photo"); + return; + } + if (config.fontFamily === CUSTOM_FONT_FAMILY && !fontFile) { + setError("Upload a custom font or pick a preset font"); + return; + } + setError(null); + setDownloadHref(null); + setBusy({ kind: "generate", current: 0, total: config.count }); + const fd = new FormData(); + fd.append("image", imageFile); + if (config.fontFamily === CUSTOM_FONT_FAMILY && fontFile) { + fd.append("font", fontFile); + } + fd.append("config", JSON.stringify(config)); + try { + const res = await fetch("/api/generate", { method: "POST", body: fd }); + const contentType = res.headers.get("content-type") ?? ""; + if (!contentType.includes("ndjson")) { + const body = (await res.json().catch(() => null)) as + | { error?: string } + | null; + throw new Error(body?.error || `Generate failed (${res.status})`); + } + await readNdjson(res, (ev) => { + if (ev.phase === "generate") { + setBusy({ kind: "generate", current: ev.current, total: ev.total }); + } else if (ev.phase === "zip") { + setBusy({ kind: "zip", current: ev.current, total: ev.total }); + } else if (ev.phase === "done") { + setDownloadHref(`/api/download/${ev.id}`); + setBusy({ kind: "idle" }); + } else if (ev.phase === "error") { + throw new Error(ev.message); + } + }); + setBusy({ kind: "idle" }); + } catch (err) { + setBusy({ kind: "idle" }); + setError(err instanceof Error ? err.message : "Generate failed"); + } + }; + + const busyLabel = + busy.kind === "generate" + ? `Generating ${busy.current} / ${busy.total}` + : busy.kind === "zip" + ? `Zipping ${busy.current} / ${busy.total}` + : "Generate"; + const progress = + busy.kind === "idle" + ? 0 + : busy.total > 0 + ? Math.round((busy.current / busy.total) * 100) + : 0; + const fontOptions = [ + ...PRESET_FONT_FAMILIES, + ...(fontFile || config.fontFamily === CUSTOM_FONT_FAMILY + ? [CUSTOM_FONT_FAMILY] + : []), + ]; + + return ( +
+
+
+

+ Founders card design +

+

+ {savedAt + ? `Autosaved locally ${new Date(savedAt).toLocaleTimeString()}` + : ready + ? "Autosave ready" + : "Loading saved config…"} + {saveError ? ` · ${saveError}` : ""} +

+
+ + ← Dashboard + +
+ +
+ { + setConfig((c) => ({ ...c, start: id })); + }} + /> +
{ + e.preventDefault(); + setDropActive(true); + }} + onDragLeave={() => setDropActive(false)} + onDrop={onDropFile} + > + {imageLoaded ? ( + + ) : imageFile ? ( +
+ Loading image… +
+ ) : ( + + )} +
+ + +
+
+ ); +} diff --git a/src/app/founders-card-design/page.tsx b/src/app/founders-card-design/page.tsx new file mode 100644 index 0000000..32ca521 --- /dev/null +++ b/src/app/founders-card-design/page.tsx @@ -0,0 +1,38 @@ +import type { Metadata } from "next"; +import { AdminHeader } from "@/components/admin-header"; +import { logPageAccess } from "@/lib/auth/log-page-access"; +import { canWritePage, navPageAccess } from "@/lib/auth/permissions"; +import { requirePageRead } from "@/lib/auth/require-session"; +import { listEarlyPlayerEmails } from "@/lib/card-gen/early-player-emails"; +import { FoundersCardEditor } from "./editor"; + +export const dynamic = "force-dynamic"; + +export async function generateMetadata(): Promise { + return { + title: "Founders card design · Kick Kings Admin", + }; +} + +export default async function FoundersCardDesignPage() { + const account = await requirePageRead("founders-card"); + await logPageAccess(account, "founders-card-design"); + const canGenerate = canWritePage(account, "founders-card"); + const emails = await listEarlyPlayerEmails(); + + return ( +
+ + +
+ ); +} diff --git a/src/app/globals.css b/src/app/globals.css index a2dc41e..56a597e 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -24,3 +24,83 @@ body { color: var(--foreground); font-family: Arial, Helvetica, sans-serif; } + +@font-face { + font-family: "Inter"; + src: url("/fonts/Inter-Regular.ttf") format("truetype"); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Inter"; + src: url("/fonts/Inter-Bold.ttf") format("truetype"); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Roboto"; + src: url("/fonts/Roboto-Regular.ttf") format("truetype"); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Roboto"; + src: url("/fonts/Roboto-Bold.ttf") format("truetype"); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Oswald"; + src: url("/fonts/Oswald-Regular.ttf") format("truetype"); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Oswald"; + src: url("/fonts/Oswald-Bold.ttf") format("truetype"); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Montserrat"; + src: url("/fonts/Montserrat-Regular.ttf") format("truetype"); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Montserrat"; + src: url("/fonts/Montserrat-Bold.ttf") format("truetype"); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Playfair Display"; + src: url("/fonts/PlayfairDisplay-Regular.ttf") format("truetype"); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: "Playfair Display"; + src: url("/fonts/PlayfairDisplay-Bold.ttf") format("truetype"); + font-weight: 700; + font-style: normal; + font-display: swap; +} diff --git a/src/app/ledger-book/page.tsx b/src/app/ledger-book/page.tsx index 350e1f0..3c9d292 100644 --- a/src/app/ledger-book/page.tsx +++ b/src/app/ledger-book/page.tsx @@ -4,6 +4,7 @@ import Link from "next/link"; import { redirect } from "next/navigation"; import { AdminHeader } from "@/components/admin-header"; import { logPageAccess } from "@/lib/auth/log-page-access"; +import { navPageAccess } from "@/lib/auth/permissions"; import { requirePageRead } from "@/lib/auth/require-session"; import { formatRcDecimalFromCoinsBigInt, @@ -149,7 +150,12 @@ export default async function LedgerBookPage({ return (
- +

diff --git a/src/app/page.tsx b/src/app/page.tsx index 98d85e1..8fd1ad6 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,6 +4,7 @@ import { EditUserCcRcOverlay } from "@/components/edit-user-cc-rc-overlay"; import { canReadPage, canWritePage, + navPageAccess, tabToPageKey, } from "@/lib/auth/permissions"; import { requireSession } from "@/lib/auth/require-session"; @@ -104,14 +105,7 @@ export default async function Home({ const account = await requireSession(); const canWritePlayers = canWritePage(account, "players"); const canWriteLedger = canWritePage(account, "ledger"); - const pageAccess = { - players: canReadPage(account, "players"), - matches: canReadPage(account, "matches"), - analysis: canReadPage(account, "analysis"), - matchmaker: canReadPage(account, "matchmaker"), - ledger: canReadPage(account, "ledger"), - logs: canReadPage(account, "logs"), - }; + const pageAccess = navPageAccess(account); const sp = await searchParams; const tabParam = firstSearchParam(sp.tab); @@ -414,7 +408,14 @@ export default async function Home({ return (
- + {configError ? (
{editUser ? ( diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index f2ff726..ab3dfad 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -2,6 +2,7 @@ import type { Metadata } from "next"; import { requireAdmin } from "@/lib/auth/require-session"; import { listSessionAccounts } from "@/lib/auth/accounts-store"; import { logPageAccess } from "@/lib/auth/log-page-access"; +import { navPageAccess } from "@/lib/auth/permissions"; import { AdminHeader } from "@/components/admin-header"; import { AdminSettingsEditor } from "@/components/admin-settings-editor"; import { AdminAccountsEditor } from "@/components/admin-accounts-editor"; @@ -68,7 +69,12 @@ export default async function SettingsPage({ return (
- +

diff --git a/src/components/admin-accounts-editor.tsx b/src/components/admin-accounts-editor.tsx index 2a40bed..62beb1f 100644 --- a/src/components/admin-accounts-editor.tsx +++ b/src/components/admin-accounts-editor.tsx @@ -7,6 +7,7 @@ import { updateAdminAccount, } from "@/app/actions/account-actions"; import { + emptyPagePermissions, PAGE_KEYS, type PageKey, type PagePermissions, @@ -20,6 +21,7 @@ const PAGE_LABELS: Record = { matchmaker: "Matchmaker", ledger: "Ledger", logs: "System logs", + "founders-card": "Founders card", }; type Props = { @@ -254,14 +256,9 @@ function AccountEditForm({ } function AddAccountForm() { - const [permissions, setPermissions] = useState({ - players: { read: false, write: false }, - matches: { read: false, write: false }, - analysis: { read: false, write: false }, - matchmaker: { read: false, write: false }, - ledger: { read: false, write: false }, - logs: { read: false, write: false }, - }); + const [permissions, setPermissions] = useState(() => + emptyPagePermissions(), + ); return (
- [ - "inline-flex items-center rounded-lg px-4 py-2 text-sm font-medium transition", - active - ? "bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900" - : "bg-zinc-100 text-zinc-700 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-300 dark:hover:bg-zinc-700", - ].join(" "); - function editHref(u: DbUser): string { return buildDashboardHref({ tab, @@ -468,10 +449,6 @@ export function AdminDashboard({ }); } - const totalUsersLabel = - statsBundle?.stats?.totalUsers ?? users.length; - const totalMatchesLabel = - statsBundle?.stats?.totalMatches ?? matches.length; const statusLabel = (status: number | null) => { if (status === 2) return "Final"; if (status === 1) return "Live"; @@ -481,126 +458,6 @@ export function AdminDashboard({ return (
-
- - Overview - - {pageAccess.players ? ( - - Players ( - {totalUsersLabel.toLocaleString("en-US")} - {!statsBundle?.stats - ? ` · table ${users.length.toLocaleString("en-US")}` - : null} - ) - - ) : null} - {pageAccess.matches ? ( - - Matches ( - {totalMatchesLabel.toLocaleString("en-US")} - {!statsBundle?.stats - ? ` · table ${matches.length.toLocaleString("en-US")}` - : null} - ) - - ) : null} - {pageAccess.analysis ? ( - 0 - ? analysisPlayerIds.join(",") - : null, - })} - className={tabClass(tab === "analysis")} - scroll={false} - > - Analysis - - ) : null} - {pageAccess.matchmaker ? ( - - Matchmaker - - ) : null} - {pageAccess.ledger ? ( - - Ledger - - ) : null} - {pageAccess.logs ? ( - - System logs - - ) : null} - {isAdmin ? ( - - Settings - - ) : null} -
-
{tab === "dashboard" ? (
diff --git a/src/components/admin-header.tsx b/src/components/admin-header.tsx index 60c1cd6..5815321 100644 --- a/src/components/admin-header.tsx +++ b/src/components/admin-header.tsx @@ -1,39 +1,67 @@ "use client"; +import { + AdminNavTabs, + type AdminNavTab, +} from "@/components/admin-nav-tabs"; +import type { NavPageAccess } from "@/lib/auth/permissions"; + type Props = { username?: string; isAdmin?: boolean; + pageAccess?: NavPageAccess; + activeTab?: AdminNavTab; + playersLabel?: string; + matchesLabel?: string; }; -export function AdminHeader({ username, isAdmin = false }: Props) { +export function AdminHeader({ + username, + isAdmin = false, + pageAccess, + activeTab = "overview", + playersLabel, + matchesLabel, +}: Props) { async function logout() { await fetch("/api/auth/logout", { method: "POST" }); window.location.href = "/login"; } return ( -
-
-

- Kick Kings Admin Dashboard -

- {username ? ( -

- Signed in as{" "} - - {username} - - {isAdmin ? " · admin" : null} -

- ) : null} +
+
+
+

+ Kick Kings Admin Dashboard +

+ {username ? ( +

+ Signed in as{" "} + + {username} + + {isAdmin ? " · admin" : null} +

+ ) : null} +
+
- + {pageAccess ? ( + + ) : null}
); } diff --git a/src/components/admin-nav-tabs.tsx b/src/components/admin-nav-tabs.tsx new file mode 100644 index 0000000..cfb71e4 --- /dev/null +++ b/src/components/admin-nav-tabs.tsx @@ -0,0 +1,109 @@ +"use client"; + +import Link from "next/link"; +import type { NavPageAccess } from "@/lib/auth/permissions"; + +export type AdminNavTab = + | "overview" + | "players" + | "matches" + | "analysis" + | "matchmaker" + | "ledger" + | "logs" + | "founders-card" + | "settings"; + +type Props = { + active: AdminNavTab; + pageAccess: NavPageAccess; + isAdmin?: boolean; + playersLabel?: string; + matchesLabel?: string; +}; + +function tabClass(active: boolean) { + return [ + "inline-flex items-center rounded-lg px-4 py-2 text-sm font-medium transition", + active + ? "bg-zinc-900 text-white dark:bg-zinc-100 dark:text-zinc-900" + : "bg-zinc-100 text-zinc-700 hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-300 dark:hover:bg-zinc-700", + ].join(" "); +} + +export function AdminNavTabs({ + active, + pageAccess, + isAdmin = false, + playersLabel = "Players", + matchesLabel = "Matches", +}: Props) { + return ( + + ); +} diff --git a/src/lib/auth/page-access-labels.ts b/src/lib/auth/page-access-labels.ts index b7c8ee2..c0f850c 100644 --- a/src/lib/auth/page-access-labels.ts +++ b/src/lib/auth/page-access-labels.ts @@ -7,6 +7,8 @@ const PAGE_LABELS: Record = { ledger: "Ledger", logs: "System logs", settings: "Settings", + "founders-card": "Founders card", + "founders-card-design": "Founders card design", "ledger-book": "Ledger book", "match-log": "Match log", "match-replay": "Match replay", diff --git a/src/lib/auth/permissions.ts b/src/lib/auth/permissions.ts index 17864d3..7b55392 100644 --- a/src/lib/auth/permissions.ts +++ b/src/lib/auth/permissions.ts @@ -5,6 +5,7 @@ export const PAGE_KEYS = [ "matchmaker", "ledger", "logs", + "founders-card", ] as const; export type PageKey = (typeof PAGE_KEYS)[number]; @@ -27,6 +28,7 @@ export function emptyPagePermissions(): PagePermissions { matchmaker: { read: false, write: false }, ledger: { read: false, write: false }, logs: { read: false, write: false }, + "founders-card": { read: false, write: false }, }; } @@ -38,6 +40,7 @@ export function fullPagePermissions(): PagePermissions { matchmaker: { read: true, write: true }, ledger: { read: true, write: true }, logs: { read: true, write: false }, + "founders-card": { read: true, write: true }, }; } @@ -66,6 +69,28 @@ export type SessionAccount = { permissions: PagePermissions; }; +export type NavPageAccess = { + players: boolean; + matches: boolean; + analysis: boolean; + matchmaker: boolean; + ledger: boolean; + logs: boolean; + foundersCard: boolean; +}; + +export function navPageAccess(account: SessionAccount): NavPageAccess { + return { + players: canReadPage(account, "players"), + matches: canReadPage(account, "matches"), + analysis: canReadPage(account, "analysis"), + matchmaker: canReadPage(account, "matchmaker"), + ledger: canReadPage(account, "ledger"), + logs: canReadPage(account, "logs"), + foundersCard: canReadPage(account, "founders-card"), + }; +} + export function canReadPage( account: SessionAccount, page: PageKey, diff --git a/src/lib/card-gen/cors.ts b/src/lib/card-gen/cors.ts new file mode 100644 index 0000000..12236a3 --- /dev/null +++ b/src/lib/card-gen/cors.ts @@ -0,0 +1,13 @@ +export const FOUNDERS_CARD_CORS = { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET, POST, OPTIONS", + "Access-Control-Allow-Headers": "Content-Type", + "Access-Control-Expose-Headers": "X-Founder-Id", +} as const; + +export function foundersCardJsonError(message: string, status: number) { + return Response.json( + { error: message }, + { status, headers: { ...FOUNDERS_CARD_CORS, "Cache-Control": "no-store" } }, + ); +} diff --git a/src/lib/card-gen/create-zip.ts b/src/lib/card-gen/create-zip.ts new file mode 100644 index 0000000..4368a01 --- /dev/null +++ b/src/lib/card-gen/create-zip.ts @@ -0,0 +1,30 @@ +import { ZipArchive } from "archiver"; +import { createWriteStream } from "node:fs"; + +export function createZipFromDir( + pngDir: string, + zipPath: string, + onProgress: (current: number, total: number) => void, +): Promise { + const output = createWriteStream(zipPath); + const archive = new ZipArchive({ zlib: { level: 6 } }); + + archive.on("progress", (p) => { + const total = Math.max(1, p.entries.total); + onProgress(p.entries.processed, total); + }); + + const done = new Promise((resolve, reject) => { + output.on("close", () => resolve()); + output.on("error", reject); + archive.on("error", reject); + archive.on("warning", (err) => { + if (err.code === "ENOENT") return; + reject(err); + }); + }); + + archive.pipe(output); + archive.directory(pngDir, false); + return archive.finalize().then(() => done); +} diff --git a/src/lib/card-gen/draw-id.ts b/src/lib/card-gen/draw-id.ts new file mode 100644 index 0000000..de6c2c7 --- /dev/null +++ b/src/lib/card-gen/draw-id.ts @@ -0,0 +1,118 @@ +import { + fontString, + hexToRgba, + type DrawStyle, +} from "@/lib/card-gen/id-config"; + +export type TextMetricsBox = { + x: number; + y: number; + baselineY: number; + width: number; + height: number; + ascent: number; + descent: number; +}; + +type MeasureCtx = { + font: string; + textAlign: CanvasTextAlign; + textBaseline: CanvasTextBaseline; + measureText: (text: string) => TextMetrics; + fillStyle: string | CanvasGradient | CanvasPattern; + strokeStyle: string | CanvasGradient | CanvasPattern; + lineWidth: number; + lineJoin: CanvasLineJoin; + miterLimit: number; + shadowColor: string; + shadowBlur: number; + shadowOffsetX: number; + shadowOffsetY: number; + fillText: (text: string, x: number, y: number) => void; + strokeText: (text: string, x: number, y: number) => void; +}; + +function applyShadow(ctx: MeasureCtx, style: DrawStyle) { + if (!style.shadowEnabled) { + clearShadow(ctx); + return; + } + ctx.shadowColor = hexToRgba(style.shadowColor, style.shadowOpacity); + ctx.shadowBlur = style.shadowBlur; + ctx.shadowOffsetX = style.shadowOffsetX; + ctx.shadowOffsetY = style.shadowOffsetY; +} + +function clearShadow(ctx: MeasureCtx) { + ctx.shadowColor = "rgba(0,0,0,0)"; + ctx.shadowBlur = 0; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 0; +} + +export function measureIdBox( + ctx: MeasureCtx, + text: string, + canvasWidth: number, + canvasHeight: number, + style: DrawStyle, +): TextMetricsBox { + ctx.font = fontString(style); + ctx.textAlign = style.align; + ctx.textBaseline = "alphabetic"; + const metrics = ctx.measureText(text); + const ascent = + Number.isFinite(metrics.actualBoundingBoxAscent) && + metrics.actualBoundingBoxAscent > 0 + ? metrics.actualBoundingBoxAscent + : style.fontSize * 0.8; + const descent = + Number.isFinite(metrics.actualBoundingBoxDescent) && + metrics.actualBoundingBoxDescent > 0 + ? metrics.actualBoundingBoxDescent + : style.fontSize * 0.2; + const x = (style.xPercent / 100) * canvasWidth; + const y = (style.yPercent / 100) * canvasHeight; + const baselineY = y + (ascent - descent) / 2; + const width = metrics.width; + let left = x; + if (style.align === "center") left = x - width / 2; + else if (style.align === "right") left = x - width; + return { + x: left, + y: baselineY - ascent, + baselineY, + width, + height: ascent + descent, + ascent, + descent, + }; +} + +export function drawIdText( + ctx: MeasureCtx, + text: string, + canvasWidth: number, + canvasHeight: number, + style: DrawStyle, +): TextMetricsBox { + const box = measureIdBox(ctx, text, canvasWidth, canvasHeight, style); + const drawX = (style.xPercent / 100) * canvasWidth; + + applyShadow(ctx, style); + if (style.outlineEnabled && style.outlineWidth > 0) { + ctx.lineJoin = "round"; + ctx.miterLimit = 2; + ctx.lineWidth = style.outlineWidth; + ctx.strokeStyle = hexToRgba(style.outlineColor, style.outlineOpacity); + ctx.strokeText(text, drawX, box.baselineY); + } + clearShadow(ctx); + if (!style.outlineEnabled && style.shadowEnabled) { + applyShadow(ctx, style); + } + ctx.fillStyle = style.color; + ctx.fillText(text, drawX, box.baselineY); + clearShadow(ctx); + return box; +} diff --git a/src/lib/card-gen/early-player-emails.ts b/src/lib/card-gen/early-player-emails.ts new file mode 100644 index 0000000..ec24352 --- /dev/null +++ b/src/lib/card-gen/early-player-emails.ts @@ -0,0 +1,115 @@ +import { createAdminSupabase } from "@/lib/supabase/admin"; + +export const EARLY_PLAYER_EMAILS_TABLE = "early_player_emails"; + +export type EarlyPlayerEmailRow = { + id: number; + created_at: string; + email: string; + preset: string; +}; + +function asId(value: unknown): number | null { + const n = typeof value === "number" ? value : Number(value); + if (!Number.isInteger(n) || n < 1) return null; + return n; +} + +export function normalizeSignupEmail(raw: string): string | null { + const email = raw.trim().toLowerCase(); + if (email.length < 3 || email.length > 254) return null; + if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) return null; + return email; +} + +function parseRow(raw: unknown): EarlyPlayerEmailRow | null { + if (!raw || typeof raw !== "object") return null; + const row = raw as Record; + const id = asId(row.id); + const email = typeof row.email === "string" ? row.email : ""; + const preset = typeof row.preset === "string" ? row.preset : ""; + const created_at = + typeof row.created_at === "string" ? row.created_at : ""; + if (id == null || !email || !created_at) return null; + return { id, created_at, email, preset: preset || "founder-card-5" }; +} + +export async function listEarlyPlayerEmails(): Promise< + { rows: EarlyPlayerEmailRow[] } | { error: string } +> { + const supabase = createAdminSupabase(); + if (!supabase) { + return { + error: + "Set NEXT_PUBLIC_SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY in .env.local.", + }; + } + + const pageSize = 1000; + const rows: EarlyPlayerEmailRow[] = []; + let offset = 0; + + for (;;) { + const { data, error } = await supabase + .from(EARLY_PLAYER_EMAILS_TABLE) + .select("id, created_at, email, preset") + .order("id", { ascending: false }) + .range(offset, offset + pageSize - 1); + + if (error) return { error: error.message }; + + const batch = (data ?? []) + .map(parseRow) + .filter((row): row is EarlyPlayerEmailRow => row != null); + rows.push(...batch); + + if (!data || data.length < pageSize) break; + offset += pageSize; + } + + return { rows }; +} + +export async function upsertEarlyPlayerEmail( + email: string, + preset: string, +): Promise<{ id: number } | { error: string; status: number }> { + const supabase = createAdminSupabase(); + if (!supabase) { + return { + error: + "Set NEXT_PUBLIC_SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY in .env.local.", + status: 503, + }; + } + + const inserted = await supabase + .from(EARLY_PLAYER_EMAILS_TABLE) + .insert({ email, preset }) + .select("id") + .single(); + + if (!inserted.error) { + const id = asId(inserted.data?.id); + if (id == null) return { error: "Could not read founder id", status: 500 }; + return { id }; + } + + if (inserted.error.code === "23505") { + const existing = await supabase + .from(EARLY_PLAYER_EMAILS_TABLE) + .select("id") + .eq("email", email) + .single(); + const id = asId(existing.data?.id); + if (id == null) { + return { error: "Email already registered", status: 409 }; + } + return { id }; + } + + return { + error: inserted.error.message || "Could not save email", + status: 500, + }; +} diff --git a/src/lib/card-gen/file-ext.ts b/src/lib/card-gen/file-ext.ts new file mode 100644 index 0000000..fa4a4ef --- /dev/null +++ b/src/lib/card-gen/file-ext.ts @@ -0,0 +1,18 @@ +export function extFromFileName( + name: string, + mime: string, + fallback: string, +): string { + const m = /\.([a-z0-9]+)$/i.exec(name); + if (m) return `.${m[1]!.toLowerCase()}`; + if (mime === "image/png") return ".png"; + if (mime === "image/jpeg") return ".jpg"; + if (mime === "image/webp") return ".webp"; + if (mime === "font/otf" || mime === "application/x-font-otf") return ".otf"; + if (mime === "font/ttf" || mime === "application/x-font-ttf") return ".ttf"; + return fallback; +} + +export function extFromFile(file: File, fallback: string): string { + return extFromFileName(file.name, file.type, fallback); +} diff --git a/src/lib/card-gen/font-files.ts b/src/lib/card-gen/font-files.ts new file mode 100644 index 0000000..6c67b6c --- /dev/null +++ b/src/lib/card-gen/font-files.ts @@ -0,0 +1,24 @@ +import path from "node:path"; +import { CUSTOM_FONT_FAMILY } from "@/lib/card-gen/id-config"; +import { PRESET_FONTS } from "@/lib/card-gen/fonts"; + +export function fontsDir(): string { + return path.join(process.cwd(), "public", "fonts"); +} + +export function fontEntriesForFamily( + family: string, + customFontPath?: string | null, +): { path: string; family: string }[] { + if (family === CUSTOM_FONT_FAMILY) { + if (!customFontPath) return []; + return [{ path: customFontPath, family: CUSTOM_FONT_FAMILY }]; + } + const preset = PRESET_FONTS.find((f) => f.family === family); + if (!preset) return []; + const dir = fontsDir(); + return [ + { path: path.join(dir, preset.regularFile), family: preset.family }, + { path: path.join(dir, preset.boldFile), family: preset.family }, + ]; +} diff --git a/src/lib/card-gen/fonts.ts b/src/lib/card-gen/fonts.ts new file mode 100644 index 0000000..94e7120 --- /dev/null +++ b/src/lib/card-gen/fonts.ts @@ -0,0 +1,35 @@ +export type PresetFont = { + family: string; + regularFile: string; + boldFile: string; +}; + +export const PRESET_FONTS: PresetFont[] = [ + { + family: "Inter", + regularFile: "Inter-Regular.ttf", + boldFile: "Inter-Bold.ttf", + }, + { + family: "Roboto", + regularFile: "Roboto-Regular.ttf", + boldFile: "Roboto-Bold.ttf", + }, + { + family: "Oswald", + regularFile: "Oswald-Regular.ttf", + boldFile: "Oswald-Bold.ttf", + }, + { + family: "Montserrat", + regularFile: "Montserrat-Regular.ttf", + boldFile: "Montserrat-Bold.ttf", + }, + { + family: "Playfair Display", + regularFile: "PlayfairDisplay-Regular.ttf", + boldFile: "PlayfairDisplay-Bold.ttf", + }, +]; + +export const PRESET_FONT_FAMILIES = PRESET_FONTS.map((f) => f.family); diff --git a/src/lib/card-gen/generate-pool.ts b/src/lib/card-gen/generate-pool.ts new file mode 100644 index 0000000..b086913 --- /dev/null +++ b/src/lib/card-gen/generate-pool.ts @@ -0,0 +1,90 @@ +import { createRequire } from "node:module"; +import os from "node:os"; +import path from "node:path"; +import type { DrawStyle } from "@/lib/card-gen/id-config"; + +export type GenerateTask = { + text: string; + outPath: string; +}; + +export type WorkerFont = { + path: string; + family: string; +}; + +type WorkerMsg = + | { type: "progress" } + | { type: "error"; message: string }; + +export async function generatePngsInWorkers(args: { + imagePath: string; + fonts: WorkerFont[]; + style: DrawStyle; + tasks: GenerateTask[]; + onProgress: (current: number, total: number) => void; +}): Promise { + const { imagePath, fonts, style, tasks, onProgress } = args; + if (tasks.length === 0) return; + + const require = createRequire(path.join(process.cwd(), "package.json")); + const threads = require("node:worker_threads") as typeof import("node:worker_threads"); + + const workerCount = Math.max( + 1, + Math.min(os.cpus().length || 1, 8, tasks.length), + ); + const buckets: GenerateTask[][] = Array.from( + { length: workerCount }, + () => [], + ); + tasks.forEach((task, i) => { + buckets[i % workerCount]!.push(task); + }); + + const workerPath = path.join(process.cwd(), "workers", "generate-id.cjs"); + let completed = 0; + const total = tasks.length; + + await Promise.all( + buckets + .filter((bucket) => bucket.length > 0) + .map( + (bucket) => + new Promise((resolve, reject) => { + const worker = new threads.Worker(workerPath, { + workerData: { + imagePath, + fonts, + style, + tasks: bucket, + }, + }); + let settled = false; + const fail = (err: Error) => { + if (settled) return; + settled = true; + void worker.terminate(); + reject(err); + }; + worker.on("message", (msg: WorkerMsg) => { + if (msg?.type === "progress") { + completed += 1; + onProgress(completed, total); + return; + } + if (msg?.type === "error") { + fail(new Error(msg.message || "Worker error")); + } + }); + worker.on("error", (err) => fail(err)); + worker.on("exit", (code) => { + if (settled) return; + settled = true; + if (code === 0) resolve(); + else reject(new Error(`Worker exited with code ${code}`)); + }); + }), + ), + ); +} diff --git a/src/lib/card-gen/id-config.ts b/src/lib/card-gen/id-config.ts new file mode 100644 index 0000000..da13442 --- /dev/null +++ b/src/lib/card-gen/id-config.ts @@ -0,0 +1,295 @@ +export type TextAlign = "left" | "center" | "right"; + +export type DrawStyle = { + fontFamily: string; + fontSize: number; + color: string; + bold: boolean; + italic: boolean; + align: TextAlign; + xPercent: number; + yPercent: number; + shadowEnabled: boolean; + shadowColor: string; + shadowOpacity: number; + shadowBlur: number; + shadowOffsetX: number; + shadowOffsetY: number; + outlineEnabled: boolean; + outlineColor: string; + outlineOpacity: number; + outlineWidth: number; +}; + +export type GenerateConfig = DrawStyle & { + prefix: string; + suffix: string; + start: number; + pad: number; + count: number; +}; + +export const CUSTOM_FONT_FAMILY = "CustomUpload"; + +export const LIMITS = { + count: { min: 1, max: 1000 }, + pad: { min: 0, max: 6 }, + start: { min: 0, max: 1_000_000 }, + fontSize: { min: 8, max: 400 }, + xPercent: { min: 0, max: 100 }, + yPercent: { min: 0, max: 100 }, + opacity: { min: 0, max: 1 }, + shadowBlur: { min: 0, max: 80 }, + shadowOffset: { min: -200, max: 200 }, + outlineWidth: { min: 0, max: 40 }, + imageBytes: 10 * 1024 * 1024, + fontBytes: 5 * 1024 * 1024, +} as const; + +const HEX_RE = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/; + +export const DEFAULT_CONFIG: GenerateConfig = { + prefix: "KK", + suffix: "", + start: 1, + pad: 4, + count: 1000, + fontFamily: "Inter", + fontSize: 48, + color: "#111111", + bold: false, + italic: false, + align: "center", + xPercent: 50, + yPercent: 50, + shadowEnabled: false, + shadowColor: "#000000", + shadowOpacity: 0.75, + shadowBlur: 8, + shadowOffsetX: 2, + shadowOffsetY: 2, + outlineEnabled: false, + outlineColor: "#ffffff", + outlineOpacity: 1, + outlineWidth: 3, +}; + +export function formatId( + prefix: string, + n: number, + pad: number, + suffix: string, +): string { + return `${prefix}${String(n).padStart(pad, "0")}${suffix}`; +} + +export function sampleId(config: GenerateConfig): string { + return formatId(config.prefix, config.start, config.pad, config.suffix); +} + +export function sanitizeFilename(id: string): string { + const cleaned = id.replace(/[/\\:*?"<>|]/g, "").trim(); + return cleaned || "id"; +} + +export function isHexColor(value: string): boolean { + return HEX_RE.test(value.trim()); +} + +export function parseHexColor( + hex: string, +): { r: number; g: number; b: number; a: number } | null { + const raw = hex.trim(); + if (!HEX_RE.test(raw)) return null; + const h = raw.slice(1); + if (h.length === 3) { + return { + r: parseInt(h[0]! + h[0], 16), + g: parseInt(h[1]! + h[1], 16), + b: parseInt(h[2]! + h[2], 16), + a: 1, + }; + } + if (h.length === 6) { + return { + r: parseInt(h.slice(0, 2), 16), + g: parseInt(h.slice(2, 4), 16), + b: parseInt(h.slice(4, 6), 16), + a: 1, + }; + } + return { + r: parseInt(h.slice(0, 2), 16), + g: parseInt(h.slice(2, 4), 16), + b: parseInt(h.slice(4, 6), 16), + a: parseInt(h.slice(6, 8), 16) / 255, + }; +} + +export function hexToRgba(hex: string, opacity: number): string { + const c = parseHexColor(hex) ?? { r: 0, g: 0, b: 0, a: 1 }; + const a = Math.max(0, Math.min(1, c.a * opacity)); + return `rgba(${c.r}, ${c.g}, ${c.b}, ${a})`; +} + +export function fontString(style: DrawStyle): string { + const italic = style.italic ? "italic " : ""; + const weight = style.bold ? 700 : 400; + return `${italic}${weight} ${style.fontSize}px "${style.fontFamily}"`; +} + +function asNumber(value: unknown, fallback: number): number { + if (typeof value === "number" && Number.isFinite(value)) return value; + if (typeof value === "string" && value.trim() !== "") { + const n = Number(value); + if (Number.isFinite(n)) return n; + } + return fallback; +} + +function clamp(n: number, min: number, max: number): number { + return Math.min(max, Math.max(min, n)); +} + +function asInt(value: unknown, fallback: number, min: number, max: number): number { + return clamp(Math.trunc(asNumber(value, fallback)), min, max); +} + +function asBool(value: unknown, fallback: boolean): boolean { + if (typeof value === "boolean") return value; + return fallback; +} + +function asAlign(value: unknown): TextAlign { + if (value === "left" || value === "center" || value === "right") return value; + return "center"; +} + +function asColor(value: unknown, fallback: string): string { + if (typeof value === "string" && isHexColor(value)) return value.trim(); + return fallback; +} + +export function parseGenerateConfig(input: unknown): GenerateConfig | null { + if (!input || typeof input !== "object") return null; + const o = input as Record; + const prefix = typeof o.prefix === "string" ? o.prefix : DEFAULT_CONFIG.prefix; + const suffix = typeof o.suffix === "string" ? o.suffix : DEFAULT_CONFIG.suffix; + const fontFamily = + typeof o.fontFamily === "string" && o.fontFamily.trim() + ? o.fontFamily.trim() + : DEFAULT_CONFIG.fontFamily; + + return { + prefix, + suffix, + start: asInt(o.start, DEFAULT_CONFIG.start, LIMITS.start.min, LIMITS.start.max), + pad: asInt(o.pad, DEFAULT_CONFIG.pad, LIMITS.pad.min, LIMITS.pad.max), + count: asInt(o.count, DEFAULT_CONFIG.count, LIMITS.count.min, LIMITS.count.max), + fontFamily, + fontSize: asInt( + o.fontSize, + DEFAULT_CONFIG.fontSize, + LIMITS.fontSize.min, + LIMITS.fontSize.max, + ), + color: asColor(o.color, DEFAULT_CONFIG.color), + bold: asBool(o.bold, DEFAULT_CONFIG.bold), + italic: asBool(o.italic, DEFAULT_CONFIG.italic), + align: asAlign(o.align), + xPercent: clamp( + asNumber(o.xPercent, DEFAULT_CONFIG.xPercent), + LIMITS.xPercent.min, + LIMITS.xPercent.max, + ), + yPercent: clamp( + asNumber(o.yPercent, DEFAULT_CONFIG.yPercent), + LIMITS.yPercent.min, + LIMITS.yPercent.max, + ), + shadowEnabled: asBool(o.shadowEnabled, DEFAULT_CONFIG.shadowEnabled), + shadowColor: asColor(o.shadowColor, DEFAULT_CONFIG.shadowColor), + shadowOpacity: clamp( + asNumber(o.shadowOpacity, DEFAULT_CONFIG.shadowOpacity), + LIMITS.opacity.min, + LIMITS.opacity.max, + ), + shadowBlur: clamp( + asNumber(o.shadowBlur, DEFAULT_CONFIG.shadowBlur), + LIMITS.shadowBlur.min, + LIMITS.shadowBlur.max, + ), + shadowOffsetX: clamp( + asNumber(o.shadowOffsetX, DEFAULT_CONFIG.shadowOffsetX), + LIMITS.shadowOffset.min, + LIMITS.shadowOffset.max, + ), + shadowOffsetY: clamp( + asNumber(o.shadowOffsetY, DEFAULT_CONFIG.shadowOffsetY), + LIMITS.shadowOffset.min, + LIMITS.shadowOffset.max, + ), + outlineEnabled: asBool(o.outlineEnabled, DEFAULT_CONFIG.outlineEnabled), + outlineColor: asColor(o.outlineColor, DEFAULT_CONFIG.outlineColor), + outlineOpacity: clamp( + asNumber(o.outlineOpacity, DEFAULT_CONFIG.outlineOpacity), + LIMITS.opacity.min, + LIMITS.opacity.max, + ), + outlineWidth: clamp( + asNumber(o.outlineWidth, DEFAULT_CONFIG.outlineWidth), + LIMITS.outlineWidth.min, + LIMITS.outlineWidth.max, + ), + }; +} + +export function pickDrawStyle(config: GenerateConfig): DrawStyle { + return { + fontFamily: config.fontFamily, + fontSize: config.fontSize, + color: config.color, + bold: config.bold, + italic: config.italic, + align: config.align, + xPercent: config.xPercent, + yPercent: config.yPercent, + shadowEnabled: config.shadowEnabled, + shadowColor: config.shadowColor, + shadowOpacity: config.shadowOpacity, + shadowBlur: config.shadowBlur, + shadowOffsetX: config.shadowOffsetX, + shadowOffsetY: config.shadowOffsetY, + outlineEnabled: config.outlineEnabled, + outlineColor: config.outlineColor, + outlineOpacity: config.outlineOpacity, + outlineWidth: config.outlineWidth, + }; +} + +export const IMAGE_MIME = new Set([ + "image/png", + "image/jpeg", + "image/jpg", + "image/webp", +]); + +export const FONT_MIME = new Set([ + "font/ttf", + "font/otf", + "font/sfnt", + "application/x-font-ttf", + "application/x-font-otf", + "application/font-sfnt", + "application/octet-stream", +]); + +export function isImageFile(file: { name: string; type: string }): boolean { + if (IMAGE_MIME.has(file.type.toLowerCase())) return true; + return /\.(png|jpe?g|webp)$/i.test(file.name); +} + +export function isFontFile(file: { name: string; type: string }): boolean { + if (FONT_MIME.has(file.type.toLowerCase())) return true; + return /\.(ttf|otf)$/i.test(file.name); +} diff --git a/src/lib/card-gen/jobs.ts b/src/lib/card-gen/jobs.ts new file mode 100644 index 0000000..aa7b591 --- /dev/null +++ b/src/lib/card-gen/jobs.ts @@ -0,0 +1,71 @@ +import { mkdir, readdir, rm, stat } from "node:fs/promises"; +import os from "node:os"; +import path from "node:path"; +import { randomUUID } from "node:crypto"; + +const JOB_TTL_MS = 15 * 60 * 1000; +const UUID_RE = + /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; + +export type JobDir = { + id: string; + dir: string; + pngDir: string; + zipPath: string; +}; + +export function jobsRoot(): string { + return path.join(os.tmpdir(), "kk-card-jobs"); +} + +export function isValidJobId(id: string): boolean { + return UUID_RE.test(id); +} + +export function jobPaths(id: string): JobDir { + const dir = path.join(jobsRoot(), id); + return { + id, + dir, + pngDir: path.join(dir, "png"), + zipPath: path.join(dir, "ids.zip"), + }; +} + +export async function sweepExpiredJobs(now = Date.now()): Promise { + const root = jobsRoot(); + let names: string[]; + try { + names = await readdir(root); + } catch (err) { + const code = (err as NodeJS.ErrnoException).code; + if (code === "ENOENT") return; + throw err; + } + await Promise.all( + names.map(async (name) => { + if (!isValidJobId(name)) { + await rm(path.join(root, name), { recursive: true, force: true }); + return; + } + const dir = path.join(root, name); + try { + const st = await stat(dir); + if (now - st.mtimeMs > JOB_TTL_MS) { + await rm(dir, { recursive: true, force: true }); + } + } catch { + // ignore races + } + }), + ); +} + +export async function createJobDir(): Promise { + await mkdir(jobsRoot(), { recursive: true }); + await sweepExpiredJobs(); + const id = randomUUID(); + const job = jobPaths(id); + await mkdir(job.pngDir, { recursive: true }); + return job; +} diff --git a/src/lib/card-gen/local-store.ts b/src/lib/card-gen/local-store.ts new file mode 100644 index 0000000..f835f66 --- /dev/null +++ b/src/lib/card-gen/local-store.ts @@ -0,0 +1,212 @@ +import { + DEFAULT_CONFIG, + parseGenerateConfig, + type GenerateConfig, +} from "@/lib/card-gen/id-config"; + +const DB_NAME = "kk-founders-card"; +const DB_VERSION = 1; +const KV_STORE = "kv"; +const PRESET_STORE = "presets"; +const DRAFT_KEY = "draft"; +const ACTIVE_PRESET_KEY = "activePresetId"; + +export type CardDraft = { + config: GenerateConfig; + image: File | null; + font: File | null; + activePresetId: string | null; + savedAt: number; +}; + +export type CardPreset = { + id: string; + name: string; + config: GenerateConfig; + image: File | null; + font: File | null; + createdAt: number; + updatedAt: number; +}; + +function fileFromBlob( + blob: Blob | File | null | undefined, + fallbackName: string, +): File | null { + if (!blob) return null; + if (blob instanceof File) return blob; + const name = + typeof (blob as Blob & { name?: string }).name === "string" && + (blob as Blob & { name?: string }).name + ? (blob as Blob & { name: string }).name + : fallbackName; + return new File([blob], name, { + type: blob.type || "application/octet-stream", + lastModified: Date.now(), + }); +} + +function openDb(): Promise { + return new Promise((resolve, reject) => { + const req = indexedDB.open(DB_NAME, DB_VERSION); + req.onupgradeneeded = () => { + const db = req.result; + if (!db.objectStoreNames.contains(KV_STORE)) { + db.createObjectStore(KV_STORE); + } + if (!db.objectStoreNames.contains(PRESET_STORE)) { + db.createObjectStore(PRESET_STORE, { keyPath: "id" }); + } + }; + req.onsuccess = () => resolve(req.result); + req.onerror = () => reject(req.error ?? new Error("IndexedDB open failed")); + }); +} + +function idbReq(req: IDBRequest): Promise { + return new Promise((resolve, reject) => { + req.onsuccess = () => resolve(req.result); + req.onerror = () => reject(req.error ?? new Error("IndexedDB request failed")); + }); +} + +function txDone(tx: IDBTransaction): Promise { + return new Promise((resolve, reject) => { + tx.oncomplete = () => resolve(); + tx.onabort = () => reject(tx.error ?? new Error("IndexedDB abort")); + tx.onerror = () => reject(tx.error ?? new Error("IndexedDB error")); + }); +} + +function normalizePreset(raw: unknown): CardPreset | null { + if (!raw || typeof raw !== "object") return null; + const o = raw as Record; + if (typeof o.id !== "string" || !o.id) return null; + if (typeof o.name !== "string" || !o.name.trim()) return null; + const config = parseGenerateConfig(o.config) ?? DEFAULT_CONFIG; + return { + id: o.id, + name: o.name.trim(), + config, + image: fileFromBlob(o.image as Blob | File | null, "base.png"), + font: fileFromBlob(o.font as Blob | File | null, "custom.ttf"), + createdAt: typeof o.createdAt === "number" ? o.createdAt : Date.now(), + updatedAt: typeof o.updatedAt === "number" ? o.updatedAt : Date.now(), + }; +} + +export async function loadDraft(): Promise { + const db = await openDb(); + try { + const tx = db.transaction([KV_STORE], "readonly"); + const store = tx.objectStore(KV_STORE); + const [rawDraft, rawPresetId] = await Promise.all([ + idbReq(store.get(DRAFT_KEY)), + idbReq(store.get(ACTIVE_PRESET_KEY)), + ]); + await txDone(tx); + const draftObj = + rawDraft && typeof rawDraft === "object" + ? (rawDraft as Record) + : null; + const config = parseGenerateConfig(draftObj?.config) ?? DEFAULT_CONFIG; + return { + config, + image: fileFromBlob(draftObj?.image as Blob | File | null, "base.png"), + font: fileFromBlob(draftObj?.font as Blob | File | null, "custom.ttf"), + activePresetId: + typeof rawPresetId === "string" && rawPresetId ? rawPresetId : null, + savedAt: typeof draftObj?.savedAt === "number" ? draftObj.savedAt : 0, + }; + } finally { + db.close(); + } +} + +export async function saveDraft(input: { + config: GenerateConfig; + image: File | null; + font: File | null; + activePresetId: string | null; +}): Promise { + const db = await openDb(); + const savedAt = Date.now(); + try { + const tx = db.transaction([KV_STORE], "readwrite"); + const store = tx.objectStore(KV_STORE); + store.put( + { + config: input.config, + image: input.image, + font: input.font, + savedAt, + }, + DRAFT_KEY, + ); + store.put(input.activePresetId, ACTIVE_PRESET_KEY); + await txDone(tx); + return savedAt; + } finally { + db.close(); + } +} + +export async function listPresets(): Promise { + const db = await openDb(); + try { + const tx = db.transaction([PRESET_STORE], "readonly"); + const raw = await idbReq(tx.objectStore(PRESET_STORE).getAll()); + await txDone(tx); + const presets = (Array.isArray(raw) ? raw : []) + .map(normalizePreset) + .filter((p): p is CardPreset => p !== null); + presets.sort((a, b) => a.createdAt - b.createdAt); + return presets; + } finally { + db.close(); + } +} + +export async function savePreset(input: { + id?: string; + name: string; + config: GenerateConfig; + image: File | null; + font: File | null; +}): Promise { + const name = input.name.trim(); + if (!name) throw new Error("Preset name is required"); + const now = Date.now(); + const existing = input.id + ? (await listPresets()).find((p) => p.id === input.id) + : undefined; + const preset: CardPreset = { + id: existing?.id ?? input.id ?? crypto.randomUUID(), + name, + config: input.config, + image: input.image, + font: input.font, + createdAt: existing?.createdAt ?? now, + updatedAt: now, + }; + const db = await openDb(); + try { + const tx = db.transaction([PRESET_STORE], "readwrite"); + tx.objectStore(PRESET_STORE).put(preset); + await txDone(tx); + return preset; + } finally { + db.close(); + } +} + +export async function deletePreset(id: string): Promise { + const db = await openDb(); + try { + const tx = db.transaction([PRESET_STORE], "readwrite"); + tx.objectStore(PRESET_STORE).delete(id); + await txDone(tx); + } finally { + db.close(); + } +} diff --git a/src/lib/card-gen/preset-api.ts b/src/lib/card-gen/preset-api.ts new file mode 100644 index 0000000..8a07d8c --- /dev/null +++ b/src/lib/card-gen/preset-api.ts @@ -0,0 +1,114 @@ +import type { GenerateConfig } from "@/lib/card-gen/id-config"; +import { savePreset, type CardPreset } from "@/lib/card-gen/local-store"; + +export type ServerPresetMeta = { + id: string; + name: string; + config: GenerateConfig; + imageName: string; + hasImage: boolean; + fontName: string | null; + hasFont: boolean; + createdAt: number; + updatedAt: number; +}; + +async function readError(res: Response): Promise { + const body = (await res.json().catch(() => null)) as { error?: string } | null; + return body?.error || `Request failed (${res.status})`; +} + +export async function fetchServerPresetList(): Promise { + const res = await fetch("/api/founders-card/presets", { cache: "no-store" }); + if (!res.ok) throw new Error(await readError(res)); + const body = (await res.json()) as { presets?: ServerPresetMeta[] }; + return Array.isArray(body.presets) ? body.presets : []; +} + +async function fileFromEndpoint( + url: string, + fallbackName: string, +): Promise { + const res = await fetch(url, { cache: "no-store" }); + if (!res.ok) return null; + const blob = await res.blob(); + if (blob.size === 0) return null; + const name = + /filename="([^"]+)"/i.exec(res.headers.get("content-disposition") ?? "")?.[1] ?? + fallbackName; + return new File([blob], name, { + type: blob.type || "application/octet-stream", + }); +} + +export async function fetchServerPresets(): Promise { + const list = await fetchServerPresetList(); + const out: CardPreset[] = []; + for (const meta of list) { + const image = meta.hasImage + ? await fileFromEndpoint( + `/api/founders-card/presets/${meta.id}/image`, + meta.imageName || "base.png", + ) + : null; + const font = meta.hasFont + ? await fileFromEndpoint( + `/api/founders-card/presets/${meta.id}/font`, + meta.fontName || "custom.ttf", + ) + : null; + out.push({ + id: meta.id, + name: meta.name, + config: meta.config, + image, + font, + createdAt: meta.createdAt, + updatedAt: meta.updatedAt, + }); + } + return out; +} + +export async function pushPresetToServer(input: { + id?: string; + name: string; + config: GenerateConfig; + image: File | null; + font: File | null; +}): Promise { + const fd = new FormData(); + fd.append("name", input.name); + fd.append("config", JSON.stringify(input.config)); + if (input.id) fd.append("id", input.id); + if (input.image) fd.append("image", input.image); + if (input.font) fd.append("font", input.font); + if (!input.font) fd.append("clearFont", "1"); + const res = await fetch("/api/founders-card/presets", { + method: "POST", + body: fd, + }); + if (!res.ok) throw new Error(await readError(res)); + return (await res.json()) as ServerPresetMeta; +} + +export async function deleteServerPreset(id: string): Promise { + const res = await fetch(`/api/founders-card/presets/${id}`, { + method: "DELETE", + }); + if (!res.ok && res.status !== 404) throw new Error(await readError(res)); +} + +export async function cacheServerPresetsLocally( + presets: CardPreset[], +): Promise { + for (const preset of presets) { + await savePreset({ + id: preset.id, + name: preset.name, + config: preset.config, + image: preset.image, + font: preset.font, + }); + } +} diff --git a/src/lib/card-gen/preset-store.ts b/src/lib/card-gen/preset-store.ts new file mode 100644 index 0000000..80d270d --- /dev/null +++ b/src/lib/card-gen/preset-store.ts @@ -0,0 +1,242 @@ +import { mkdir, readFile, readdir, rename, rm, writeFile } from "node:fs/promises"; +import path from "node:path"; +import { randomUUID } from "node:crypto"; +import { + parseGenerateConfig, + type GenerateConfig, +} from "@/lib/card-gen/id-config"; +import { extFromFileName } from "@/lib/card-gen/file-ext"; + +const UUID_RE = + /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; + +export type PresetMeta = { + id: string; + name: string; + config: GenerateConfig; + imageFile: string; + imageName: string; + fontFile: string | null; + fontName: string | null; + createdAt: number; + updatedAt: number; +}; + +export type LoadedPreset = PresetMeta & { + dir: string; + imagePath: string; + fontPath: string | null; +}; + +export function presetsRoot(): string { + const override = process.env.FOUNDERS_CARD_PRESETS_PATH?.trim(); + if (override) return path.resolve(override); + return path.join(process.cwd(), "data", "founders-card-presets"); +} + +export function isPresetId(id: string): boolean { + return UUID_RE.test(id); +} + +function presetDir(id: string): string { + return path.join(presetsRoot(), id); +} + +function namesEqual(a: string, b: string): boolean { + return a.trim().toLowerCase() === b.trim().toLowerCase(); +} + +let writeChain: Promise = Promise.resolve(); + +function enqueueWrite(fn: () => Promise): Promise { + const next = writeChain.then(fn, fn); + writeChain = next.then( + () => undefined, + () => undefined, + ); + return next; +} + +function parseMeta(raw: unknown, id: string): PresetMeta | null { + if (!raw || typeof raw !== "object") return null; + const o = raw as Record; + const name = typeof o.name === "string" ? o.name.trim() : ""; + if (!name) return null; + const config = parseGenerateConfig(o.config); + if (!config) return null; + if (typeof o.imageFile !== "string" || !o.imageFile) return null; + if (o.imageFile.includes("..") || o.imageFile.includes("/") || o.imageFile.includes("\\")) { + return null; + } + let fontFile: string | null = + typeof o.fontFile === "string" && o.fontFile ? o.fontFile : null; + if ( + fontFile && + (fontFile.includes("..") || fontFile.includes("/") || fontFile.includes("\\")) + ) { + fontFile = null; + } + return { + id, + name, + config, + imageFile: o.imageFile, + imageName: + typeof o.imageName === "string" && o.imageName.trim() + ? o.imageName.trim() + : "base.png", + fontFile, + fontName: + typeof o.fontName === "string" && o.fontName.trim() + ? o.fontName.trim() + : null, + createdAt: typeof o.createdAt === "number" ? o.createdAt : Date.now(), + updatedAt: typeof o.updatedAt === "number" ? o.updatedAt : Date.now(), + }; +} + +async function readMeta(id: string): Promise { + if (!isPresetId(id)) return null; + try { + const text = await readFile(path.join(presetDir(id), "meta.json"), "utf8"); + return parseMeta(JSON.parse(text) as unknown, id); + } catch { + return null; + } +} + +async function writeMeta(meta: PresetMeta): Promise { + const dir = presetDir(meta.id); + await mkdir(dir, { recursive: true }); + const filePath = path.join(dir, "meta.json"); + const tmp = `${filePath}.${process.pid}.${Date.now()}.tmp`; + await writeFile(tmp, `${JSON.stringify(meta, null, 2)}\n`, "utf8"); + await rename(tmp, filePath); +} + +export async function listPresetMeta(): Promise { + await mkdir(presetsRoot(), { recursive: true }); + let names: string[]; + try { + names = await readdir(presetsRoot()); + } catch { + return []; + } + const out: PresetMeta[] = []; + for (const name of names) { + const meta = await readMeta(name); + if (meta) out.push(meta); + } + out.sort((a, b) => a.createdAt - b.createdAt); + return out; +} + +export async function getLoadedPreset(id: string): Promise { + const meta = await readMeta(id); + if (!meta) return null; + const dir = presetDir(meta.id); + const imagePath = path.join(dir, meta.imageFile); + const fontPath = meta.fontFile ? path.join(dir, meta.fontFile) : null; + return { ...meta, dir, imagePath, fontPath }; +} + +export async function findPresetByName( + name: string, +): Promise { + const needle = name.trim(); + if (!needle) return null; + const all = await listPresetMeta(); + const match = all.find((p) => namesEqual(p.name, needle)); + if (!match) return null; + return getLoadedPreset(match.id); +} + +export async function saveStoredPreset(input: { + id?: string; + name: string; + config: GenerateConfig; + image?: { bytes: Buffer; name: string; type: string } | null; + font?: { bytes: Buffer; name: string; type: string } | null; + clearFont?: boolean; +}): Promise { + const name = input.name.trim(); + if (!name) throw new Error("Preset name is required"); + + return enqueueWrite(async () => { + const all = await listPresetMeta(); + const byId = input.id ? all.find((p) => p.id === input.id) : undefined; + const byName = all.find((p) => namesEqual(p.name, name)); + const existing = byId ?? byName; + if (byId && byName && byId.id !== byName.id) { + throw new Error("A preset with that name already exists"); + } + if (!existing && !input.image) { + throw new Error("Image is required"); + } + const now = Date.now(); + const id = + existing?.id ?? + (input.id && isPresetId(input.id) ? input.id : randomUUID()); + const dir = presetDir(id); + await mkdir(dir, { recursive: true }); + + let imageFile = existing?.imageFile ?? ""; + let imageName = existing?.imageName ?? "base.png"; + if (input.image) { + const ext = extFromFileName(input.image.name, input.image.type, ".png"); + imageFile = `image${ext}`; + imageName = input.image.name; + const dest = path.join(dir, imageFile); + const tmp = `${dest}.${process.pid}.tmp`; + await writeFile(tmp, input.image.bytes); + await rename(tmp, dest); + if (existing?.imageFile && existing.imageFile !== imageFile) { + await rm(path.join(dir, existing.imageFile), { force: true }); + } + } + if (!imageFile) throw new Error("Image is required"); + + let fontFile = existing?.fontFile ?? null; + let fontName = existing?.fontName ?? null; + if (input.clearFont) { + if (fontFile) await rm(path.join(dir, fontFile), { force: true }); + fontFile = null; + fontName = null; + } else if (input.font) { + const ext = extFromFileName(input.font.name, input.font.type, ".ttf"); + fontFile = `font${ext}`; + fontName = input.font.name; + const dest = path.join(dir, fontFile); + const tmp = `${dest}.${process.pid}.tmp`; + await writeFile(tmp, input.font.bytes); + await rename(tmp, dest); + if (existing?.fontFile && existing.fontFile !== fontFile) { + await rm(path.join(dir, existing.fontFile), { force: true }); + } + } + + const meta: PresetMeta = { + id, + name, + config: input.config, + imageFile, + imageName, + fontFile, + fontName, + createdAt: existing?.createdAt ?? now, + updatedAt: now, + }; + await writeMeta(meta); + return meta; + }); +} + +export async function deleteStoredPreset(id: string): Promise { + if (!isPresetId(id)) return false; + return enqueueWrite(async () => { + const existing = await readMeta(id); + if (!existing) return false; + await rm(presetDir(id), { recursive: true, force: true }); + return true; + }); +} diff --git a/src/lib/card-gen/progress.ts b/src/lib/card-gen/progress.ts new file mode 100644 index 0000000..31397ac --- /dev/null +++ b/src/lib/card-gen/progress.ts @@ -0,0 +1,16 @@ +export type GenerateProgressEvent = + | { phase: "generate"; current: number; total: number } + | { phase: "zip"; current: number; total: number } + | { phase: "done"; id: string } + | { phase: "error"; message: string }; + +export function isProgressEvent(value: unknown): value is GenerateProgressEvent { + if (!value || typeof value !== "object") return false; + const o = value as Record; + if (o.phase === "generate" || o.phase === "zip") { + return typeof o.current === "number" && typeof o.total === "number"; + } + if (o.phase === "done") return typeof o.id === "string"; + if (o.phase === "error") return typeof o.message === "string"; + return false; +} diff --git a/src/lib/card-gen/public-rate-limit.ts b/src/lib/card-gen/public-rate-limit.ts new file mode 100644 index 0000000..fc90c88 --- /dev/null +++ b/src/lib/card-gen/public-rate-limit.ts @@ -0,0 +1,40 @@ +const WINDOW_MS = 60_000; +const MAX_CARD_HITS = 60; +const MAX_SIGNUP_HITS = 10; + +const cardHitsByIp = new Map(); +const signupHitsByIp = new Map(); + +function checkLimit( + store: Map, + ip: string, + maxHits: number, +): { allowed: true } | { allowed: false; retryAfterSeconds: number } { + const now = Date.now(); + const cutoff = now - WINDOW_MS; + const prev = store.get(ip) ?? []; + const recent = prev.filter((t) => t > cutoff); + if (recent.length >= maxHits) { + const retryAfterSeconds = Math.max( + 1, + Math.ceil((recent[0]! + WINDOW_MS - now) / 1000), + ); + store.set(ip, recent); + return { allowed: false, retryAfterSeconds }; + } + recent.push(now); + store.set(ip, recent); + return { allowed: true }; +} + +export function checkPublicCardRateLimit( + ip: string, +): { allowed: true } | { allowed: false; retryAfterSeconds: number } { + return checkLimit(cardHitsByIp, ip, MAX_CARD_HITS); +} + +export function checkPublicSignupRateLimit( + ip: string, +): { allowed: true } | { allowed: false; retryAfterSeconds: number } { + return checkLimit(signupHitsByIp, ip, MAX_SIGNUP_HITS); +} diff --git a/src/lib/card-gen/render-one.ts b/src/lib/card-gen/render-one.ts new file mode 100644 index 0000000..3992e30 --- /dev/null +++ b/src/lib/card-gen/render-one.ts @@ -0,0 +1,27 @@ +import { readFile, rm } from "node:fs/promises"; +import path from "node:path"; +import type { DrawStyle } from "@/lib/card-gen/id-config"; +import { generatePngsInWorkers, type WorkerFont } from "@/lib/card-gen/generate-pool"; +import { createJobDir } from "@/lib/card-gen/jobs"; + +export async function renderOnePng(args: { + imagePath: string; + fonts: WorkerFont[]; + style: DrawStyle; + text: string; +}): Promise { + const job = await createJobDir(); + try { + const outPath = path.join(job.pngDir, "card.png"); + await generatePngsInWorkers({ + imagePath: args.imagePath, + fonts: args.fonts, + style: args.style, + tasks: [{ text: args.text, outPath }], + onProgress: () => undefined, + }); + return await readFile(outPath); + } finally { + await rm(job.dir, { recursive: true, force: true }); + } +} diff --git a/src/lib/card-gen/render-public.ts b/src/lib/card-gen/render-public.ts new file mode 100644 index 0000000..26553df --- /dev/null +++ b/src/lib/card-gen/render-public.ts @@ -0,0 +1,91 @@ +import { + CUSTOM_FONT_FAMILY, + formatId, + LIMITS, + pickDrawStyle, + sanitizeFilename, +} from "@/lib/card-gen/id-config"; +import { fontEntriesForFamily } from "@/lib/card-gen/font-files"; +import { PRESET_FONT_FAMILIES } from "@/lib/card-gen/fonts"; +import { findPresetByName } from "@/lib/card-gen/preset-store"; +import { renderOnePng } from "@/lib/card-gen/render-one"; + +export const DEFAULT_SIGNUP_PRESET = "founder-card-5"; + +export type RenderCardResult = + | { ok: true; png: Buffer; filename: string } + | { ok: false; status: number; error: string }; + +export async function renderFoundersCardPng( + presetName: string, + founderId: number, +): Promise { + if ( + !Number.isInteger(founderId) || + founderId < LIMITS.start.min || + founderId > LIMITS.start.max + ) { + return { + ok: false, + status: 400, + error: `id must be between ${LIMITS.start.min} and ${LIMITS.start.max}`, + }; + } + + const preset = await findPresetByName(presetName); + if (!preset) return { ok: false, status: 404, error: "Preset not found" }; + + const config = preset.config; + if ( + config.fontFamily !== CUSTOM_FONT_FAMILY && + !PRESET_FONT_FAMILIES.includes(config.fontFamily) + ) { + return { ok: false, status: 400, error: "Preset font is invalid" }; + } + if (config.fontFamily === CUSTOM_FONT_FAMILY && !preset.fontPath) { + return { + ok: false, + status: 400, + error: "Preset is missing its custom font", + }; + } + + const fonts = fontEntriesForFamily(config.fontFamily, preset.fontPath); + if (fonts.length === 0) { + return { ok: false, status: 500, error: "Could not resolve fonts" }; + } + + const text = formatId(config.prefix, founderId, config.pad, config.suffix); + const filename = `${sanitizeFilename(text)}.png`; + try { + const png = await renderOnePng({ + imagePath: preset.imagePath, + fonts, + style: pickDrawStyle(config), + text, + }); + return { ok: true, png, filename }; + } catch (err) { + return { + ok: false, + status: 500, + error: err instanceof Error ? err.message : "Generate failed", + }; + } +} + +export function pngResponse( + png: Buffer, + filename: string, + extraHeaders?: Record, +): Response { + return new Response(new Uint8Array(png), { + headers: { + "Content-Type": "image/png", + "Content-Length": String(png.length), + "Content-Disposition": `inline; filename="${filename}"`, + "Cache-Control": "no-store", + ...extraHeaders, + }, + }); +} diff --git a/src/types/database.ts b/src/types/database.ts index 7c88886..7700303 100644 --- a/src/types/database.ts +++ b/src/types/database.ts @@ -56,6 +56,14 @@ export type DbTransaction = { match_id: number | null; }; +/** Mirrors `public.early_player_emails` (see schemas/early_player_emails.md). */ +export type DbEarlyPlayerEmail = { + id: number; + created_at: string; + email: string; + preset: string; +}; + /** Mirrors `public.ping_reports` (see schemas/ping_reports.md). */ export type DbPingReport = { id: number; diff --git a/workers/generate-id.cjs b/workers/generate-id.cjs new file mode 100644 index 0000000..b4d36d9 --- /dev/null +++ b/workers/generate-id.cjs @@ -0,0 +1,128 @@ +"use strict"; + +const { parentPort, workerData } = require("node:worker_threads"); +const { writeFile } = require("node:fs/promises"); +const { createCanvas, loadImage, GlobalFonts } = require("@napi-rs/canvas"); + +function parseHexColor(hex) { + const raw = String(hex || "").trim(); + const m = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.exec(raw); + if (!m) return { r: 0, g: 0, b: 0, a: 1 }; + const h = m[1]; + if (h.length === 3) { + return { + r: parseInt(h[0] + h[0], 16), + g: parseInt(h[1] + h[1], 16), + b: parseInt(h[2] + h[2], 16), + a: 1, + }; + } + if (h.length === 6) { + return { + r: parseInt(h.slice(0, 2), 16), + g: parseInt(h.slice(2, 4), 16), + b: parseInt(h.slice(4, 6), 16), + a: 1, + }; + } + return { + r: parseInt(h.slice(0, 2), 16), + g: parseInt(h.slice(2, 4), 16), + b: parseInt(h.slice(4, 6), 16), + a: parseInt(h.slice(6, 8), 16) / 255, + }; +} + +function hexToRgba(hex, opacity) { + const c = parseHexColor(hex); + const a = Math.max(0, Math.min(1, c.a * opacity)); + return `rgba(${c.r}, ${c.g}, ${c.b}, ${a})`; +} + +function fontString(style) { + const italic = style.italic ? "italic " : ""; + const weight = style.bold ? 700 : 400; + return `${italic}${weight} ${style.fontSize}px "${style.fontFamily}"`; +} + +function applyShadow(ctx, style) { + if (!style.shadowEnabled) { + clearShadow(ctx); + return; + } + ctx.shadowColor = hexToRgba(style.shadowColor, style.shadowOpacity); + ctx.shadowBlur = style.shadowBlur; + ctx.shadowOffsetX = style.shadowOffsetX; + ctx.shadowOffsetY = style.shadowOffsetY; +} + +function clearShadow(ctx) { + ctx.shadowColor = "rgba(0,0,0,0)"; + ctx.shadowBlur = 0; + ctx.shadowOffsetX = 0; + ctx.shadowOffsetY = 0; +} + +function drawIdText(ctx, text, canvasWidth, canvasHeight, style) { + ctx.font = fontString(style); + ctx.textAlign = style.align; + ctx.textBaseline = "alphabetic"; + const metrics = ctx.measureText(text); + const ascent = + Number.isFinite(metrics.actualBoundingBoxAscent) && + metrics.actualBoundingBoxAscent > 0 + ? metrics.actualBoundingBoxAscent + : style.fontSize * 0.8; + const descent = + Number.isFinite(metrics.actualBoundingBoxDescent) && + metrics.actualBoundingBoxDescent > 0 + ? metrics.actualBoundingBoxDescent + : style.fontSize * 0.2; + const x = (style.xPercent / 100) * canvasWidth; + const y = (style.yPercent / 100) * canvasHeight; + const baselineY = y + (ascent - descent) / 2; + + applyShadow(ctx, style); + if (style.outlineEnabled && style.outlineWidth > 0) { + ctx.lineJoin = "round"; + ctx.miterLimit = 2; + ctx.lineWidth = style.outlineWidth; + ctx.strokeStyle = hexToRgba(style.outlineColor, style.outlineOpacity); + ctx.strokeText(text, x, baselineY); + } + clearShadow(ctx); + if (!style.outlineEnabled && style.shadowEnabled) { + applyShadow(ctx, style); + } + ctx.fillStyle = style.color; + ctx.fillText(text, x, baselineY); + clearShadow(ctx); +} + +async function run() { + const { imagePath, fonts, style, tasks } = workerData; + for (const font of fonts || []) { + GlobalFonts.registerFromPath(font.path, font.family); + } + const img = await loadImage(imagePath); + const canvas = createCanvas(img.width, img.height); + const ctx = canvas.getContext("2d"); + for (const task of tasks) { + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(img, 0, 0); + drawIdText(ctx, task.text, canvas.width, canvas.height, style); + const png = await canvas.encode("png"); + await writeFile(task.outPath, png); + parentPort.postMessage({ type: "progress" }); + } +} + +run().catch((err) => { + const message = err instanceof Error ? err.message : String(err); + try { + parentPort.postMessage({ type: "error", message }); + } catch { + // ignore + } + process.exitCode = 1; +});