feat!: use elysia js intead of koa				#18
		
		
	
					 2 changed files with 47 additions and 14 deletions
				
			
		| 
						 | 
				
			
			@ -29,7 +29,7 @@ export async function renderComicPage({ path, page, reqHeaders, set }: RenderOpt
 | 
			
		|||
 | 
			
		||||
		if (page < 0 || page >= entries.length) {
 | 
			
		||||
			set.status = 404;
 | 
			
		||||
			zip.reader.close();
 | 
			
		||||
			await zip.reader.close();
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +45,7 @@ export async function renderComicPage({ path, page, reqHeaders, set }: RenderOpt
 | 
			
		|||
			const cachedDate = new Date(ifModifiedSince);
 | 
			
		||||
			if (!Number.isNaN(cachedDate.valueOf()) && lastModified <= cachedDate) {
 | 
			
		||||
				set.status = 304;
 | 
			
		||||
				zip.reader.close();
 | 
			
		||||
				await zip.reader.close();
 | 
			
		||||
				return null;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -57,6 +57,14 @@ export async function renderComicPage({ path, page, reqHeaders, set }: RenderOpt
 | 
			
		|||
			},
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		let zipClosed = false;
 | 
			
		||||
		const closeZip = async () => {
 | 
			
		||||
			if (!zipClosed) {
 | 
			
		||||
				zipClosed = true;
 | 
			
		||||
				await zip.reader.close();
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		readStream.pipeTo(new WritableStream({
 | 
			
		||||
			write(chunk) {
 | 
			
		||||
				nodeReadable.push(chunk);
 | 
			
		||||
| 
						 | 
				
			
			@ -64,15 +72,21 @@ export async function renderComicPage({ path, page, reqHeaders, set }: RenderOpt
 | 
			
		|||
			close() {
 | 
			
		||||
				nodeReadable.push(null);
 | 
			
		||||
			},
 | 
			
		||||
			abort(err) {
 | 
			
		||||
				nodeReadable.destroy(err);
 | 
			
		||||
			},
 | 
			
		||||
		})).catch((err) => {
 | 
			
		||||
			nodeReadable.destroy(err);
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		nodeReadable.on("close", () => {
 | 
			
		||||
			zip.reader.close();
 | 
			
		||||
			closeZip().catch(console.error);
 | 
			
		||||
		});
 | 
			
		||||
		nodeReadable.on("error", () => {
 | 
			
		||||
			zip.reader.close();
 | 
			
		||||
			closeZip().catch(console.error);
 | 
			
		||||
		});
 | 
			
		||||
		nodeReadable.on("end", () => {
 | 
			
		||||
			closeZip().catch(console.error);
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
		const ext = entry.filename.split(".").pop()?.toLowerCase() ?? "jpeg";
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +98,7 @@ export async function renderComicPage({ path, page, reqHeaders, set }: RenderOpt
 | 
			
		|||
		set.status = 200;
 | 
			
		||||
		return nodeReadable;
 | 
			
		||||
	} catch (error) {
 | 
			
		||||
		zip.reader.close();
 | 
			
		||||
		await zip.reader.close();
 | 
			
		||||
		throw error;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,11 @@
 | 
			
		|||
import { type FileHandle, open } from "node:fs/promises";
 | 
			
		||||
import { orderBy } from "natural-orderby";
 | 
			
		||||
import { ZipReader, Reader, type Entry, ZipReaderConstructorOptions } from "@zip.js/zip.js";
 | 
			
		||||
import EventEmitter from "node:events";
 | 
			
		||||
 | 
			
		||||
class FileReader extends Reader<string> {
 | 
			
		||||
	private fd?: FileHandle;
 | 
			
		||||
	private path: string;
 | 
			
		||||
	private closed = false;
 | 
			
		||||
 | 
			
		||||
	constructor(path: string) {
 | 
			
		||||
		super(path);
 | 
			
		||||
| 
						 | 
				
			
			@ -14,21 +14,29 @@ class FileReader extends Reader<string> {
 | 
			
		|||
	
 | 
			
		||||
	async init(): Promise<void> {
 | 
			
		||||
		await super.init?.();
 | 
			
		||||
		if (this.closed) return;
 | 
			
		||||
		
 | 
			
		||||
		const fd = await open(this.path, "r");
 | 
			
		||||
		const stat = await fd.stat();
 | 
			
		||||
		this.fd = fd;
 | 
			
		||||
		this.size = stat.size;
 | 
			
		||||
		// not implemented yet
 | 
			
		||||
		(this.fd as unknown as EventEmitter).on("close", () => {
 | 
			
		||||
			this.fd?.close();
 | 
			
		||||
			this.fd = undefined;
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	async close(): Promise<void> {
 | 
			
		||||
		await this.fd?.close();
 | 
			
		||||
		if (this.closed) return;
 | 
			
		||||
		this.closed = true;
 | 
			
		||||
		
 | 
			
		||||
		if (this.fd) {
 | 
			
		||||
			await this.fd.close();
 | 
			
		||||
			this.fd = undefined;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async readUint8Array(index: number, length: number): Promise<Uint8Array> {
 | 
			
		||||
		if (this.closed) {
 | 
			
		||||
			throw new Error("FileReader is closed");
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		try {
 | 
			
		||||
			const buffer = new Uint8Array(length);
 | 
			
		||||
			if (this.fd === undefined) {
 | 
			
		||||
| 
						 | 
				
			
			@ -49,18 +57,29 @@ class FileReader extends Reader<string> {
 | 
			
		|||
			return buffer;
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			console.error("read error", error);
 | 
			
		||||
			// 에러 발생 시 파일 핸들 정리
 | 
			
		||||
			await this.close();
 | 
			
		||||
			throw error;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class FileZipReader extends ZipReader<FileHandle> {
 | 
			
		||||
	private closed = false;
 | 
			
		||||
	
 | 
			
		||||
	constructor(private reader: FileReader, options?: ZipReaderConstructorOptions) {
 | 
			
		||||
		super(reader, options);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	override async close(): Promise<void> {
 | 
			
		||||
		super.close();
 | 
			
		||||
		await this.reader.close();
 | 
			
		||||
		if (this.closed) return;
 | 
			
		||||
		this.closed = true;
 | 
			
		||||
		
 | 
			
		||||
		try {
 | 
			
		||||
			await super.close();
 | 
			
		||||
		} finally {
 | 
			
		||||
			await this.reader.close();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue