From c26c2aae3178b4fa89af02542fe26a3360999cd4 Mon Sep 17 00:00:00 2001 From: Timo Date: Fri, 10 Jul 2026 11:14:26 +0200 Subject: [PATCH] Social assets: no auto table create, manual SQL only Co-Authored-By: Claude Fable 5 --- docs/automations/social-accounts-and-jobs.md | 6 +++++- src/app/(main)/api/social-assets/route.ts | 19 +++---------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/docs/automations/social-accounts-and-jobs.md b/docs/automations/social-accounts-and-jobs.md index 205fe7b..f2b0506 100644 --- a/docs/automations/social-accounts-and-jobs.md +++ b/docs/automations/social-accounts-and-jobs.md @@ -74,7 +74,11 @@ ## QRMaster Social Asset Hosting (no-deploy image URLs) - `POST https://qrmaster.net/api/social-assets` (header `x-admin-key: `) with JSON `{ "files": [{ "filename", "mimeType", "dataBase64" }] }` stores images in PostgreSQL and returns public `https://qrmaster.net/api/social-assets/` URLs on the verified domain. - `GET /api/social-assets/` serves the file publicly (immutable cache); `GET /api/social-assets` (admin) lists the last 100 assets; `DELETE /api/social-assets/` (admin) removes one. -- Allowed types: jpeg/png/webp/mp4, max 10 MB per file. Table `SocialAsset` is auto-created on first upload (`CREATE TABLE IF NOT EXISTS`, in line with the no-migrations policy). +- Allowed types: jpeg/png/webp/mp4, max 10 MB per file. +- The `SocialAsset` table must be created manually on the server (one-time, no auto-create in the route). Run on the server: + ```bash + docker-compose exec db psql -U postgres -d qrmaster -c 'CREATE TABLE IF NOT EXISTS "SocialAsset" ("id" TEXT PRIMARY KEY, "filename" TEXT NOT NULL, "mimeType" TEXT NOT NULL, "data" BYTEA NOT NULL, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP);' + ``` - Typical carousel flow: upload slides here → pass the returned URLs as `photos` to `POST /api/tiktok/upload` → check via `/api/tiktok/upload/status?publish_id=...`. No app deploy needed per carousel. ## Refresh Behavior diff --git a/src/app/(main)/api/social-assets/route.ts b/src/app/(main)/api/social-assets/route.ts index 6a70a69..c37c656 100644 --- a/src/app/(main)/api/social-assets/route.ts +++ b/src/app/(main)/api/social-assets/route.ts @@ -22,19 +22,9 @@ const ALLOWED_MIME_TYPES = new Set([ 'video/mp4', ]); -// Schema changes in this repo are applied as raw SQL against the running -// database (no Prisma migrations); this keeps the route self-bootstrapping. -async function ensureTable() { - await db.$executeRawUnsafe(` - CREATE TABLE IF NOT EXISTS "SocialAsset" ( - "id" TEXT PRIMARY KEY, - "filename" TEXT NOT NULL, - "mimeType" TEXT NOT NULL, - "data" BYTEA NOT NULL, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP - ) - `); -} +// The "SocialAsset" table is NOT created by this route. Apply the schema +// manually on the server (npm run docker:db), see +// docs/automations/social-accounts-and-jobs.md. export async function POST(request: NextRequest) { if (!isAdminRequest(request)) { @@ -82,8 +72,6 @@ export async function POST(request: NextRequest) { } try { - await ensureTable(); - const baseUrl = process.env.NEXTAUTH_URL || 'https://qrmaster.net'; const assets = []; for (const file of files) { @@ -114,7 +102,6 @@ export async function GET(request: NextRequest) { } try { - await ensureTable(); const assets = await db.socialAsset.findMany({ select: { id: true, filename: true, mimeType: true, createdAt: true }, orderBy: { createdAt: 'desc' },