shared.ts
⎇
Raw
1import path from "node:path";
2import commandExists from "command-exists";
3import type { Metadata } from "music-server-shared/types";
4import { parseArgs } from "node:util";
5
6export const coverRegex = process.env.COVER_REGEX === undefined ? /(cover)|(folder).(png|jpg)$/i : "";
7export const musicRoot = process.env.MUSIC_ROOT || "";
8if (musicRoot === "") {
9 console.error("Please define the environment variable MUSIC_ROOT");
10 process.exit(1);
11}
12
13export const [username, password] = process.env.AUTH
14 ? Buffer.from(process.env.AUTH, "base64").toString().split(":", 2)
15 : [undefined, undefined];
16
17export const authTokens = new Map<string, Date>();
18
19//clear outdated tokens once a day
20setInterval(
21 () => {
22 for (const [token, endDate] of authTokens.entries()) {
23 if (endDate.getTime() < Date.now()) authTokens.delete(token);
24 }
25 },
26 1000 * 60 * 60 * 24,
27);
28
29if (!path.isAbsolute(musicRoot)) {
30 console.error(`Music root ${musicRoot} is not absolute`);
31 process.exit(1);
32}
33
34export const excludeExtension =
35 process.env.EXCLUDE_EXTENSION === undefined
36 ? ["txt", "log", "nfo", "m3u", "htm", "html"]
37 : process.env.EXCLUDE_EXTENSION.split(",");
38
39if (!commandExists.sync("ffmpeg")) {
40 console.error("Required command ffmpeg not found in PATH");
41 process.exit(1);
42}
43if (!commandExists.sync("tar")) {
44 console.error("Required command tar not found in PATH");
45 process.exit(1);
46}
47if (!commandExists.sync("avifenc")) {
48 console.error("Required command avifenc not found in PATH");
49 process.exit(1);
50}
51
52export const { values: args } = parseArgs({
53 args: Bun.argv,
54 options: {
55 serve: {
56 type: "string",
57 },
58 },
59 strict: true,
60 allowPositionals: true,
61});
62
63if (!args.serve) {
64 console.error("Missing --serve, set it to the directory containing the frontend code");
65 process.exit(1);
66}
67
68export const mediaTypes = ["audio", "video"];
69export const allowedTypes = [...mediaTypes, "image"];
70
71export const fileTypeCache = new Map<string, string>();
72export const probeCache = new Map<string, Metadata>();
73export const generatedPlaylistIds = new Map<string, string[]>();
74
75export class PathInfo {
76 constructor(public mimeType: string) {}
77}
78
79export class ServerError {
80 constructor(
81 public status: number,
82 public error: string,
83 ) {}
84}
85