3 Commits

Author SHA1 Message Date
static
7779910949 tRPC 초기 설정 2025-11-02 23:09:01 +09:00
static
328baba395 패키지 버전 업데이트 2025-11-02 02:57:18 +09:00
static
4e91cdad95 서버로부터 파일의 DEK를 다운로드한 후에야 썸네일이 표시되던 현상 수정 2025-07-20 05:17:38 +09:00
12 changed files with 1083 additions and 880 deletions

View File

@@ -2,11 +2,7 @@
FROM node:22-alpine AS base FROM node:22-alpine AS base
WORKDIR /app WORKDIR /app
RUN apk add --no-cache bash curl && \ RUN npm install -g pnpm@10
curl -o /usr/local/bin/wait-for-it https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh && \
chmod +x /usr/local/bin/wait-for-it
RUN npm install -g pnpm@9
COPY pnpm-lock.yaml . COPY pnpm-lock.yaml .
# Build Stage # Build Stage
@@ -29,4 +25,4 @@ COPY --from=build /app/build ./build
EXPOSE 3000 EXPOSE 3000
ENV BODY_SIZE_LIMIT=Infinity ENV BODY_SIZE_LIMIT=Infinity
CMD ["bash", "-c", "wait-for-it ${DATABASE_HOST:-localhost}:${DATABASE_PORT:-5432} -- node ./build/index.js"] CMD ["node", "./build/index.js"]

View File

@@ -3,7 +3,8 @@ services:
build: . build: .
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- database database:
condition: service_healthy
user: ${CONTAINER_UID:-0}:${CONTAINER_GID:-0} user: ${CONTAINER_UID:-0}:${CONTAINER_GID:-0}
volumes: volumes:
- ./data/library:/app/data/library - ./data/library:/app/data/library
@@ -35,3 +36,8 @@ services:
environment: environment:
- POSTGRES_USER=arkvault - POSTGRES_USER=arkvault
- POSTGRES_PASSWORD=${DATABASE_PASSWORD:?} - POSTGRES_PASSWORD=${DATABASE_PASSWORD:?}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
interval: 5s
timeout: 5s
retries: 5

View File

@@ -16,53 +16,55 @@
"db:migrate": "kysely migrate" "db:migrate": "kysely migrate"
}, },
"devDependencies": { "devDependencies": {
"@eslint/compat": "^1.3.1", "@eslint/compat": "^1.4.1",
"@iconify-json/material-symbols": "^1.2.29", "@iconify-json/material-symbols": "^1.2.44",
"@sveltejs/adapter-node": "^5.2.13", "@sveltejs/adapter-node": "^5.4.0",
"@sveltejs/kit": "^2.22.5", "@sveltejs/kit": "^2.48.4",
"@sveltejs/vite-plugin-svelte": "^4.0.4", "@sveltejs/vite-plugin-svelte": "^6.2.1",
"@trpc/client": "^11.7.1",
"@types/file-saver": "^2.0.7", "@types/file-saver": "^2.0.7",
"@types/ms": "^0.7.34", "@types/ms": "^0.7.34",
"@types/node-schedule": "^2.1.8", "@types/node-schedule": "^2.1.8",
"@types/pg": "^8.15.4", "@types/pg": "^8.15.6",
"autoprefixer": "^10.4.21", "autoprefixer": "^10.4.21",
"axios": "^1.10.0", "axios": "^1.13.1",
"dexie": "^4.0.11", "dexie": "^4.2.1",
"eslint": "^9.30.1", "eslint": "^9.39.0",
"eslint-config-prettier": "^10.1.5", "eslint-config-prettier": "^10.1.8",
"eslint-plugin-svelte": "^3.10.1", "eslint-plugin-svelte": "^3.13.0",
"eslint-plugin-tailwindcss": "^3.18.0", "eslint-plugin-tailwindcss": "^3.18.2",
"exifreader": "^4.31.1", "exifreader": "^4.32.0",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"globals": "^16.3.0", "globals": "^16.5.0",
"heic2any": "^0.0.4", "heic2any": "^0.0.4",
"kysely-ctl": "^0.13.1", "kysely-ctl": "^0.19.0",
"lru-cache": "^11.1.0", "lru-cache": "^11.2.2",
"mime": "^4.0.7", "mime": "^4.1.0",
"p-limit": "^6.2.0", "p-limit": "^7.2.0",
"prettier": "^3.6.2", "prettier": "^3.6.2",
"prettier-plugin-svelte": "^3.4.0", "prettier-plugin-svelte": "^3.4.0",
"prettier-plugin-tailwindcss": "^0.6.14", "prettier-plugin-tailwindcss": "^0.7.1",
"svelte": "^5.35.6", "svelte": "^5.43.2",
"svelte-check": "^4.2.2", "svelte-check": "^4.3.3",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.18",
"typescript": "^5.8.3", "typescript": "^5.9.3",
"typescript-eslint": "^8.36.0", "typescript-eslint": "^8.46.2",
"unplugin-icons": "^22.1.0", "unplugin-icons": "^22.5.0",
"vite": "^5.4.19" "vite": "^7.1.12"
}, },
"dependencies": { "dependencies": {
"@fastify/busboy": "^3.1.1", "@fastify/busboy": "^3.2.0",
"argon2": "^0.43.0", "@trpc/server": "^11.7.1",
"kysely": "^0.28.2", "argon2": "^0.44.0",
"kysely": "^0.28.8",
"ms": "^2.1.3", "ms": "^2.1.3",
"node-schedule": "^2.1.1", "node-schedule": "^2.1.1",
"pg": "^8.16.3", "pg": "^8.16.3",
"uuid": "^11.1.0", "uuid": "^13.0.0",
"zod": "^3.25.76" "zod": "^3.25.76"
}, },
"engines": { "engines": {
"node": "^22.0.0", "node": "^22.0.0",
"pnpm": "^9.0.0" "pnpm": "^10.0.0"
} }
} }

1806
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -32,7 +32,7 @@
}; };
$effect(() => { $effect(() => {
if ($info?.dataKey) { if ($info) {
requestFileThumbnailDownload($info.id, $info.dataKey) requestFileThumbnailDownload($info.id, $info.dataKey)
.then((thumbnailUrl) => { .then((thumbnailUrl) => {
thumbnail = thumbnailUrl ?? undefined; thumbnail = thumbnailUrl ?? undefined;

View File

@@ -48,9 +48,9 @@ export const requestFileThumbnailUpload = async (
return await fetch(`/api/file/${fileId}/thumbnail/upload`, { method: "POST", body: form }); return await fetch(`/api/file/${fileId}/thumbnail/upload`, { method: "POST", body: form });
}; };
export const requestFileThumbnailDownload = async (fileId: number, dataKey: CryptoKey) => { export const requestFileThumbnailDownload = async (fileId: number, dataKey?: CryptoKey) => {
const cache = await getFileThumbnailCache(fileId); const cache = await getFileThumbnailCache(fileId);
if (cache) return cache; if (cache || !dataKey) return cache;
let res = await callGetApi(`/api/file/${fileId}/thumbnail`); let res = await callGetApi(`/api/file/${fileId}/thumbnail`);
if (!res.ok) return null; if (!res.ok) return null;

View File

@@ -34,7 +34,7 @@
}; };
$effect(() => { $effect(() => {
if ($info?.dataKey) { if ($info) {
requestFileThumbnailDownload($info.id, $info.dataKey) requestFileThumbnailDownload($info.id, $info.dataKey)
.then((thumbnailUrl) => { .then((thumbnailUrl) => {
thumbnail = thumbnailUrl ?? undefined; thumbnail = thumbnailUrl ?? undefined;

View File

@@ -0,0 +1,15 @@
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
import { createContext } from "$trpc/init.server";
import { appRouter } from "$trpc/router.server";
import type { RequestHandler } from "./$types";
const trpcHandler: RequestHandler = (event) =>
fetchRequestHandler({
endpoint: "/trpc",
req: event.request,
router: appRouter,
createContext: () => createContext(event),
});
export const GET = trpcHandler;
export const POST = trpcHandler;

23
src/trpc/client.ts Normal file
View File

@@ -0,0 +1,23 @@
import { createTRPCClient, httpBatchLink } from "@trpc/client";
import { browser } from "$app/environment";
import type { AppRouter } from "./router.server";
const createClient = (fetch: typeof globalThis.fetch) =>
createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: "/trpc",
fetch,
}),
],
});
let browserClient: ReturnType<typeof createClient>;
export const trpc = (fetch = globalThis.fetch) => {
const client = browserClient ?? createClient(fetch);
if (browser) {
browserClient ??= client;
}
return client;
};

9
src/trpc/init.server.ts Normal file
View File

@@ -0,0 +1,9 @@
import type { RequestEvent } from "@sveltejs/kit";
import { initTRPC } from "@trpc/server";
export const createContext = (event: RequestEvent) => event;
const t = initTRPC.context<Awaited<ReturnType<typeof createContext>>>().create();
export const router = t.router;
export const publicProcedure = t.procedure;

13
src/trpc/router.server.ts Normal file
View File

@@ -0,0 +1,13 @@
import type { RequestEvent } from "@sveltejs/kit";
import type { inferRouterInputs, inferRouterOutputs } from "@trpc/server";
import { createContext, router } from "./init.server";
export const appRouter = router({
// TODO
});
export const createCaller = (event: RequestEvent) => appRouter.createCaller(createContext(event));
export type AppRouter = typeof appRouter;
export type RouterInputs = inferRouterInputs<AppRouter>;
export type RouterOutputs = inferRouterOutputs<AppRouter>;

View File

@@ -3,15 +3,12 @@ import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
/** @type {import('@sveltejs/kit').Config} */ /** @type {import('@sveltejs/kit').Config} */
const config = { const config = {
// Consult https://svelte.dev/docs/kit/integrations
// for more information about preprocessors
preprocess: vitePreprocess(), preprocess: vitePreprocess(),
kit: { kit: {
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
adapter: adapter(), adapter: adapter(),
alias: {
$trpc: "./src/trpc",
},
}, },
}; };