fix running in container

AuthorKonata <konata@posteo.jp>
Date
Commit3e4045826c2df8fd12aa227f1ff7f30397288a01
Parent949ed73
6 files changed, 28 insertions(+), 22 deletions(-)
▾MContainerfile
@@ -9,6 +9,7 @@ FROM docker.io/alpine:3.21
RUN apk add catatonit ffmpeg tar libavif-apps
WORKDIR /app
COPY --from=compile /app/server/dist .
COPY --from=compile /app/server/node_modules/mediainfo.js/dist/MediaInfoModule.wasm /node_modules/mediainfo.js/dist/MediaInfoModule.wasm
ENTRYPOINT ["catatonit", "--"]
CMD ["/app/server", "--serve", "/app"]
▾Mserver/package.json
@@ -6,10 +6,11 @@
"clean": "rm -rf dist node_modules ../webclient/dist ../webclient/node_modules",
"postinstall": "bun install --cwd ../webclient",
"build-watch:frontend": "cd ../webclient && bun run build -c vite.watch.config.ts --watch --emptyOutDir --outDir ../server/dist",
"start": "bun run --watch src/index.ts --serve dist",
"copy-mediainfo-wasm": "cp node_modules/mediainfo.js/dist/MediaInfoModule.wasm dist/MediaInfoModule.wasm",
"start": "bun run copy-mediainfo-wasm && bun run --watch src/index.ts --serve dist",
"dev": "concurrently \"bun run build-watch:frontend\" \"sleep 1 && bun run start\"",
"build:frontend": "cd ../webclient && bun run build -c vite.compile.config.ts --emptyOutDir --outDir ../server/dist",
"compile": "bun run build:frontend && bun build src/index.ts --compile --production --outfile dist/server"
"compile": "bun run build:frontend && bun build src/index.ts --compile --production --outfile dist/server && bun run copy-mediainfo-wasm"
},
"devDependencies": {
"@types/command-exists": "^1.2.3",
▾Mserver/src/index.ts
@@ -1,7 +1,6 @@
import staticPlugin from "@elysiajs/static";
import { Elysia, type InferHandler, t } from "elysia";
import path, { basename } from "node:path";
import { parseArgs } from "node:util";
import {
musicRoot,
fileTypeCache,
@@ -13,6 +12,7 @@ import {
username,
password,
authTokens,
args,
} from "./shared";
import { getPathInfo, listFiles, findCover, matchesType, packWithTar, probeFile, toAvif } from "./utils";
import { stat } from "node:fs/promises";
@@ -36,22 +36,6 @@ import { convertWithFFmpeg } from "./ffmpeg";
//TODO: better ffmpeg errors
//TODO: more cover detection
const { values } = parseArgs({
args: Bun.argv,
options: {
serve: {
type: "string",
},
},
strict: true,
allowPositionals: true,
});
if (!values.serve) {
console.error("Missing --serve, set it to the directory containing the frontend code");
process.exit(1);
}
//increase timeout to not abort when listing huge folders
const setup = new Elysia({ serve: { idleTimeout: 255 } });
@@ -106,7 +90,7 @@ const downloadHandler: DownloadHandler = async ({ headers, params, set, request
};
const app = setup
.use(staticPlugin({ assets: values.serve, prefix: "/" }))
.use(staticPlugin({ assets: args.serve, prefix: "/" }))
.onBeforeHandle(({ request, path }) => {
if (path === "/remote-log") return;
console.info(request.method, path);
▾Mserver/src/shared.ts
@@ -1,6 +1,7 @@
import path from "node:path";
import commandExists from "command-exists";
import type { Metadata } from "music-server-shared/types";
import { parseArgs } from "node:util";
export const coverRegex = process.env.COVER_REGEX === undefined ? /(cover)|(folder).(png|jpg)$/i : "";
export const musicRoot = process.env.MUSIC_ROOT || "";
@@ -49,6 +50,22 @@ if (!commandExists.sync("avifenc")) {
process.exit(1);
}
export const { values: args } = parseArgs({
args: Bun.argv,
options: {
serve: {
type: "string",
},
},
strict: true,
allowPositionals: true,
});
if (!args.serve) {
console.error("Missing --serve, set it to the directory containing the frontend code");
process.exit(1);
}
export const mediaTypes = ["audio", "video"];
export const allowedTypes = [...mediaTypes, "image"];
▾Mserver/src/utils.ts
@@ -4,6 +4,7 @@ import type { FileListingWithStatus, Metadata } from "music-server-shared/types"
import { readdir, stat } from "node:fs/promises";
import path from "node:path";
import {
args,
coverRegex,
excludeExtension,
fileTypeCache,
@@ -28,7 +29,9 @@ export async function findAsync<T>(arr: Array<T>, asyncCallback: (value: T) => P
type CoverResult = { info: PathInfo; path: string } | { info: PathInfo; content: Uint8Array } | { info: ServerError };
const mediaInfo = await MediaInfo();
const mediaInfo = await MediaInfo({
locateFile: () => `${args.serve}/MediaInfoModule.wasm`,
});
export async function findCover(targetPath: string): Promise<CoverResult> {
try {
▾Mwebclient/vite.common.config.ts
@@ -4,7 +4,7 @@ import type { VitePWAOptions } from "vite-plugin-pwa";
export const pwaOptions: Partial<VitePWAOptions> = {
registerType: "autoUpdate",
workbox: {
globPatterns: ["**/*.{js,wasm,css,html,woff2}"],
globPatterns: ["**/*.{js,css,html,woff2}"],
navigateFallback: undefined,
runtimeCaching: [
{