From 6b0440602b92202dd5f97a757598b28e5f040e32 Mon Sep 17 00:00:00 2001 From: gunshiz Date: Wed, 29 Jul 2026 12:28:51 +0700 Subject: [PATCH] refactor: consolidate shared application helpers --- app/admin/form/[id]/client.tsx | 2 +- app/admin/form/[id]/extra/client.tsx | 2 +- app/cdn/[id]/route.ts | 2 +- app/form/client.tsx | 2 +- components/delete-buttons.tsx | 2 +- components/guarded-link.tsx | 2 +- hooks/use-debounced-autosave.ts | 16 +++++++++++++++- lib/admin-form-save-bridge.ts | 16 ---------------- lib/cdn-images.test.ts | 2 +- lib/cdn-images.ts | 17 +++++++++++++++++ lib/cdn-response.ts | 16 ---------------- lib/errors.ts | 3 --- lib/utils.ts | 6 +++++- package.json | 2 +- 14 files changed, 45 insertions(+), 45 deletions(-) delete mode 100644 lib/admin-form-save-bridge.ts delete mode 100644 lib/cdn-response.ts delete mode 100644 lib/errors.ts diff --git a/app/admin/form/[id]/client.tsx b/app/admin/form/[id]/client.tsx index 441c4ab..de395ac 100644 --- a/app/admin/form/[id]/client.tsx +++ b/app/admin/form/[id]/client.tsx @@ -21,7 +21,7 @@ import { import { Plus, Trash, ArrowUp, ArrowDown, Loader2, Image as ImageIcon, X, Check, GripVertical, AlertCircle } from "lucide-react"; import Image from 'next/image'; import { RichTextEditor } from "@/components/rich-text-editor"; -import { getErrorMessage } from "@/lib/errors"; +import { getErrorMessage } from "@/lib/utils"; import { Accordion, AccordionContent, diff --git a/app/admin/form/[id]/extra/client.tsx b/app/admin/form/[id]/extra/client.tsx index 113f1c6..94060d6 100644 --- a/app/admin/form/[id]/extra/client.tsx +++ b/app/admin/form/[id]/extra/client.tsx @@ -19,7 +19,7 @@ import { DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { ScrollArea } from "@/components/ui/scroll-area" -import { getErrorMessage } from "@/lib/errors"; +import { getErrorMessage } from "@/lib/utils"; import { isValidDiscordWebhookUrl, previewWebhookTemplate, diff --git a/app/cdn/[id]/route.ts b/app/cdn/[id]/route.ts index 54d62e3..23e7782 100644 --- a/app/cdn/[id]/route.ts +++ b/app/cdn/[id]/route.ts @@ -1,5 +1,5 @@ import { db } from "@/db"; -import { cdnImageResponse } from "@/lib/cdn-response"; +import { cdnImageResponse } from "@/lib/cdn-images"; export async function GET( _request: Request, diff --git a/app/form/client.tsx b/app/form/client.tsx index 0055f68..faa59ff 100644 --- a/app/form/client.tsx +++ b/app/form/client.tsx @@ -35,7 +35,7 @@ import { FormMessage, } from "@/components/ui/form"; import { DropdownMenuAvatar, DiscordMemberProfile } from "@/components/dropdown-menu-avatar"; -import { getErrorMessage } from "@/lib/errors"; +import { getErrorMessage } from "@/lib/utils"; import { Accordion, AccordionContent, diff --git a/components/delete-buttons.tsx b/components/delete-buttons.tsx index e5d7f9c..deb65f3 100644 --- a/components/delete-buttons.tsx +++ b/components/delete-buttons.tsx @@ -28,7 +28,7 @@ import { AlertDialogTrigger, } from "@/components/ui/alert-dialog"; import { Spinner } from "@/components/ui/spinner"; -import { getErrorMessage } from "@/lib/errors"; +import { getErrorMessage } from "@/lib/utils"; interface DeleteFormButtonProps { formId: string; diff --git a/components/guarded-link.tsx b/components/guarded-link.tsx index 5aa2777..f4a43a1 100644 --- a/components/guarded-link.tsx +++ b/components/guarded-link.tsx @@ -3,7 +3,7 @@ import type { ComponentProps, MouseEvent } from "react"; import Link from "next/link"; import { useRouter } from "next/navigation"; -import { flushPendingSaves } from "@/lib/admin-form-save-bridge"; +import { flushPendingSaves } from "@/hooks/use-debounced-autosave"; export function GuardedLink({ href, diff --git a/hooks/use-debounced-autosave.ts b/hooks/use-debounced-autosave.ts index d58da89..b1f6a10 100644 --- a/hooks/use-debounced-autosave.ts +++ b/hooks/use-debounced-autosave.ts @@ -1,10 +1,24 @@ "use client"; import { useCallback, useEffect, useRef, useState } from "react"; -import { registerPendingSave } from "@/lib/admin-form-save-bridge"; export type AutoSaveStatus = "clean" | "dirty" | "saving" | "saved" | "error"; +type FlushSave = () => Promise; + +const pendingSaves = new Set(); + +export function registerPendingSave(flush: FlushSave) { + pendingSaves.add(flush); + return () => { + pendingSaves.delete(flush); + }; +} + +export async function flushPendingSaves() { + await Promise.all([...pendingSaves].map((flush) => flush())); +} + export function useDebouncedAutoSave({ save, delay = 1000, diff --git a/lib/admin-form-save-bridge.ts b/lib/admin-form-save-bridge.ts deleted file mode 100644 index 7ef504a..0000000 --- a/lib/admin-form-save-bridge.ts +++ /dev/null @@ -1,16 +0,0 @@ -"use client"; - -type FlushSave = () => Promise; - -const pendingSaves = new Set(); - -export function registerPendingSave(flush: FlushSave) { - pendingSaves.add(flush); - return () => { - pendingSaves.delete(flush); - }; -} - -export async function flushPendingSaves() { - await Promise.all([...pendingSaves].map((flush) => flush())); -} diff --git a/lib/cdn-images.test.ts b/lib/cdn-images.test.ts index 51d90f7..2056378 100644 --- a/lib/cdn-images.test.ts +++ b/lib/cdn-images.test.ts @@ -1,6 +1,6 @@ import { describe, expect, test } from "bun:test"; -import { cdnImageResponse } from "@/lib/cdn-response"; import { + cdnImageResponse, MAX_FORM_ANSWER_IMAGE_BYTES, validateImageUploadFile, } from "@/lib/cdn-images"; diff --git a/lib/cdn-images.ts b/lib/cdn-images.ts index ce2ed12..e287b9a 100644 --- a/lib/cdn-images.ts +++ b/lib/cdn-images.ts @@ -27,3 +27,20 @@ export function validateImageUploadFile(file: Pick { return (html || "").replace(/<[^>]*>?/gm, '').trim(); }; @@ -17,4 +21,4 @@ export const copyToClipboard = async (text: string): Promise => { console.error("Copy error:", error); return false; } -}; \ No newline at end of file +}; diff --git a/package.json b/package.json index 1444416..3bb392b 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "start": "next start -H 0.0.0.0", "lint": "eslint", "up": "docker compose up -d --build", - "logs": "docker compose logs -f erika", + "logs": "docker compose logs -f app", "log": "docker compose logs -f", "db:generate": "drizzle-kit generate", "db:migrate": "drizzle-kit migrate",