서버, 클라이언트, 서비스 워커 공용 코드를 lib/shared로 분리하고 브라우저 전용 모듈을 lib/client로 재구성

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
staticandClaude Opus 5.5 committed 2026-10-12 00:04:56 +09:00
1 parent 6a6aa1765b
commit aee87fd9b6
82 files changed
+326 -221

No files matched your search

+7 -4
View File
@@ -2,10 +2,9 @@ import { FileRepo, MediaRepo } from "#lib/server/db/index.js";
import type { Ciphertext } from "#lib/server/db/schema/index.js";
import { AppError } from "#lib/server/errors.js";
import { createEncContentStream } from "#lib/server/storage/index.js";
import type { RangeRequest } from "#lib/shared/http.js";
import { schedulePendingFileDeletions } from "./fileDeletion";
type Range = { start?: number; end?: number };
export const getFile = async (userId: number, fileId: number) => {
const file = await FileRepo.getFile(userId, fileId);
if (!file) {
@@ -68,7 +67,7 @@ export const getFileThumbnail = async (userId: number, fileId: number) => {
const decodeIv = (iv: string | null) => (iv ? Buffer.from(iv, "base64") : undefined);
export const getFileStream = async (userId: number, fileId: number, range?: Range) => {
export const getFileStream = async (userId: number, fileId: number, range?: RangeRequest) => {
const file = await FileRepo.getFile(userId, fileId);
if (!file) {
throw new AppError("NOT_FOUND", "File not found");
@@ -76,7 +75,11 @@ export const getFileStream = async (userId: number, fileId: number, range?: Rang
return await createEncContentStream(file.path, decodeIv(file.encContentIv), range);
};
export const getFileThumbnailStream = async (userId: number, fileId: number, range?: Range) => {
export const getFileThumbnailStream = async (
userId: number,
fileId: number,
range?: RangeRequest,
) => {
const thumbnail = await getFileThumbnail(userId, fileId);
return await createEncContentStream(thumbnail.path, decodeIv(thumbnail.encContentIv), range);
};
+1 -1
View File
@@ -1,7 +1,7 @@
import { open } from "fs/promises";
import type { Readable } from "stream";
import { ENCRYPTION_OVERHEAD, ENCRYPTED_CHUNK_SIZE } from "#lib/constants/index.js";
import { AppError } from "#lib/server/errors.js";
import { ENCRYPTION_OVERHEAD, ENCRYPTED_CHUNK_SIZE } from "#lib/shared/format/index.js";
const invalidChunkSize = () => new AppError("BAD_REQUEST", "Invalid chunk size");
+7 -7
View File
@@ -2,22 +2,22 @@ import { createReadStream } from "fs";
import { stat } from "fs/promises";
import { Readable } from "stream";
import { AppError } from "#lib/server/errors.js";
import { resolveRange, type RangeRequest } from "#lib/shared/http.js";
export const createEncContentStream = async (
path: string,
iv?: Buffer,
range?: { start?: number; end?: number },
rangeRequest?: RangeRequest,
) => {
const { size: fileSize } = await stat(path);
const ivSize = iv?.byteLength ?? 0;
const totalSize = fileSize + ivSize;
const start = range?.start ?? 0;
const end = range?.end ?? totalSize - 1;
if (start > end || start < 0 || end >= totalSize) {
const range = resolveRange(rangeRequest, fileSize + ivSize);
if (!range) {
throw new AppError("RANGE_NOT_SATISFIABLE", "Invalid range");
}
const { start, end } = range;
return {
encContentStream: Readable.toWeb(
Readable.from(
@@ -34,7 +34,7 @@ export const createEncContentStream = async (
})(),
),
),
range: { start, end, total: totalSize },
isRangeRequest: !!range,
range,
isRangeRequest: !!rangeRequest,
};
};