diff --git a/flake.nix b/flake.nix index 9b63883..68d430e 100644 --- a/flake.nix +++ b/flake.nix @@ -25,7 +25,7 @@ # uncomment this and let the build fail, then get the current hash # very scuffed but endorsed! # npmDepsHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; - npmDepsHash = "sha256-7DsCZ+wDLvpqBch2rVbXiSxIaYdITX3RCHfjNx0wUKs="; + npmDepsHash = "sha256-11AayHpPu7ocBPRB5k4SU7b99Aqc/dufAy2Yg5oPvGE="; nativeBuildInputs = with pkgs; [ makeWrapper ]; diff --git a/package-lock.json b/package-lock.json index 059c73c..1a43d01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "callsites": "^4.2.0", "chalk": "^5.4.1", "data-uri-to-buffer": "^6.0.2", + "dotenv": "^17.2.1", "drizzle-orm": "^0.44.4", "express": "^5.1.0", "express-handlebars": "^8.0.3", @@ -2796,6 +2797,18 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz", + "integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/drizzle-kit": { "version": "0.31.4", "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.31.4.tgz", diff --git a/package.json b/package.json index 45c3ad6..996108e 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "callsites": "^4.2.0", "chalk": "^5.4.1", "data-uri-to-buffer": "^6.0.2", + "dotenv": "^17.2.1", "drizzle-orm": "^0.44.4", "express": "^5.1.0", "express-handlebars": "^8.0.3", diff --git a/src/cache.ts b/src/cache.ts index 12671a0..2a370d3 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -6,7 +6,6 @@ import fsPromises from "fs/promises"; import { and, eq } from "drizzle-orm"; import * as log from "./log.js"; import prettyBytes from "pretty-bytes"; -import process from "node:process"; // try creating cache if it doesn't exist // a bit scuffed but that ok @@ -27,21 +26,16 @@ try { let entriesClearedBytes = 0; log.debug("cache cleanup and expiry timers starting"); - const results = await Promise.all((await db.select().from(fileCacheTable)).map(async ({ name, expiry }) => { + await Promise.all((await db.select().from(fileCacheTable)).map(async ({ name, expiry }) => { if (expiry < Date.now()) { - return await dropFile(name); + entriesCleared++; + entriesClearedBytes += (await fsPromises.stat(path.join(config.downloader.cache.directory, name))).size; + await dropFile(name); } else { await scheduleDeletion(name, expiry); } })); - for (const result of results) { - if (result !== undefined) { - entriesCleared += 1; - entriesClearedBytes += result; - } - } - log.debug("cache cleanup complete!"); log.debug(`cleared ${entriesCleared} entr${entriesCleared === 1 ? "y" : "ies"}, freeing up ${prettyBytes(entriesClearedBytes)}!`); } catch (err) { @@ -62,26 +56,19 @@ async function scheduleDeletion(name: string, expiry: number): Promise { timers.set(name, timeout); } -// TODO: add behavior toggle: should we keep it in the database on failure or not ?? -// current behavior: delete from db first, then try deleting files -// this is good if manual cleanup was already done (we can then ignore ENOENT) -// bad if they change the permissions instead of manual removal -async function dropFile(name: string): Promise { - try { - await db.delete(fileCacheTable).where(eq(fileCacheTable.name, name)); - const size = (await fsPromises.stat(path.join(config.downloader.cache.directory, name))).size; - await fsPromises.unlink(path.join(config.downloader.cache.directory, name)); +async function dropFile(name: string): Promise { + const size = (await fsPromises.stat(path.join(config.downloader.cache.directory, name))).size; + await fsPromises.unlink(path.join(config.downloader.cache.directory, name)).catch((err) => { + if (err.code !== "ENOENT") { + log.error(`failed to delete cached file ${name} for whatever reason!`); + log.error("manual removal may be necessary!"); + log.error(err); + } + }); - log.debug(`deleted file ${name} from cache, freeing up ${prettyBytes(size)}`); + log.debug(`deleted file ${name} from cache, freeing up ${prettyBytes(size)}`); - return size; - } catch (err) { - if (err instanceof Error && err.message.includes("ENOENT")) { return; } - - log.error(`failed to delete cached file ${name} for whatever reason!`); - log.error("manual removal may be necessary!"); - log.error(err); - } + await db.delete(fileCacheTable).where(eq(fileCacheTable.name, name)); } export async function addFileToCache(fileName: string): Promise { diff --git a/src/config.ts b/src/config.ts index a03bd57..8fc5655 100644 --- a/src/config.ts +++ b/src/config.ts @@ -2,17 +2,10 @@ import fs from "node:fs"; import * as log from "./log.js"; import toml from "toml"; import { z, ZodError, ZodObject } from "zod"; +import * as dotenv from "dotenv"; import { fromZodError } from "zod-validation-error"; -import process from "node:process"; -try { - process.loadEnvFile("./.env"); -} catch (err) { - if (err instanceof Error && !err.message.includes("ENOENT")) { - log.error("error reading or parsing evv file!"); - log.error(err); - } -} +dotenv.config({ quiet: true }); const configSchema = z.object({ server: z.object({ diff --git a/src/database/index.ts b/src/database/index.ts index b41c7a2..b33804d 100644 --- a/src/database/index.ts +++ b/src/database/index.ts @@ -2,7 +2,6 @@ import { createClient } from "@libsql/client"; import { config, env } from "../config.js"; import { drizzle } from "drizzle-orm/libsql"; import { migrate } from "drizzle-orm/libsql/migrator"; -import process from "node:process"; import fsPromises from "fs/promises"; import * as log from "../log.js";