mirror of
https://github.com/FoxxMD/multi-scrobbler.git
synced 2026-07-09 17:28:28 +00:00
137 lines
No EOL
5 KiB
TypeScript
137 lines
No EOL
5 KiB
TypeScript
import express, { Router } from 'express';
|
|
import { childLogger, LogDataPretty, Logger } from "@foxxmd/logging";
|
|
import bodyParser from 'body-parser';
|
|
import { stripIndents } from "common-tags";
|
|
import session from 'express-session';
|
|
import { PassThrough } from "node:stream";
|
|
import passport from 'passport';
|
|
import path from "path";
|
|
import ViteExpress from "vite-express";
|
|
import { projectDir } from "../common/index.js";
|
|
import { getRoot } from "../ioc.js";
|
|
import { parseBool } from "../utils.js";
|
|
import { getAddress } from "../utils/NetworkUtils.js";
|
|
import { setupApi } from "./api.js";
|
|
import ScrobbleSources from '../sources/ScrobbleSources.js';
|
|
import ScrobbleClients from '../scrobblers/ScrobbleClients.js';
|
|
|
|
const app = express();
|
|
const router = Router();
|
|
|
|
export const initServer = async (parentLogger: Logger, appLoggerStream: PassThrough, initialOutput: LogDataPretty[] = [], sources: ScrobbleSources, clients: ScrobbleClients) => {
|
|
|
|
const logger = childLogger(parentLogger, 'API'); // parentLogger.child({labels: ['API']}, mergeArr);
|
|
|
|
try {
|
|
app.use(router);
|
|
app.use(bodyParser.json());
|
|
app.use(
|
|
bodyParser.urlencoded({
|
|
extended: true,
|
|
})
|
|
);
|
|
|
|
//app.use(express.static(buildDir));
|
|
|
|
app.use(session({secret: 'keyboard cat', resave: false, saveUninitialized: false}));
|
|
app.use(passport.initialize());
|
|
app.use(passport.session());
|
|
|
|
const root = getRoot();
|
|
|
|
if(root.get('disableWeb')) {
|
|
logger.warn('API and Dashboard have been DISABLED. Note that any ingress sources (Webscrobbler, Listenbrainz/Lastfm Endpoint Sources, etc...) will be unusable');
|
|
return;
|
|
}
|
|
|
|
const isProd = root.get('isProd');
|
|
const port = root.get('port');
|
|
const local = root.get('localUrl');
|
|
const localDefined = root.get('hasDefinedBaseUrl');
|
|
|
|
setupApi(app, logger, appLoggerStream, initialOutput, sources, clients);
|
|
|
|
const addy = getAddress();
|
|
const addresses: string[] = [];
|
|
let dockerHint = '';
|
|
if (parseBool(process.env.IS_DOCKER) && addy.v4 !== undefined && addy.v4.includes('172')) {
|
|
dockerHint = stripIndents`
|
|
--- HINT ---
|
|
MS is likely being run in a container with BRIDGE networking which means the above addresses are not accessible from outside this container.
|
|
To ensure the container is accessible make sure you have mapped the *container* port ${port} to a *host* port. https://docs.multi-scrobbler.app/installation/?dockerSetting=networking#recommended-settings
|
|
The container will then be accessible at http://HOST_MACHINE_IP:HOST_PORT${localDefined ? ` (or ${local} since you defined this!)` : ''}
|
|
--- HINT ---
|
|
`;
|
|
}
|
|
for (const [k, v] of Object.entries(addy)) {
|
|
if (v !== undefined) {
|
|
switch (k) {
|
|
case 'host':
|
|
case 'v4':
|
|
addresses.push(`---> ${k === 'host' ? 'Local'.padEnd(14, ' ') : 'Network'.padEnd(14, ' ')} http://${v}:${port}`);
|
|
break;
|
|
case 'v6':
|
|
addresses.push(`---> Network (IPv6) http://[${v}]:${port}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
app.use('/docs', express.static(path.resolve(projectDir, `./docsite/build`)));
|
|
|
|
if(process.env.USE_HASH_ROUTER === undefined) {
|
|
process.env.USE_HASH_ROUTER = root.get('isSubPath').toString();
|
|
}
|
|
|
|
app.get(/^\/next$/, (_, res) => {
|
|
res.redirect("/next/")
|
|
});
|
|
|
|
const viteExpressOptions: Parameters<typeof ViteExpress.config>[0] = {
|
|
mode: isProd ? 'production' : 'development',
|
|
inlineViteConfig: {
|
|
base: localDefined && local.pathname !== '/' ? local.toString() : '/'
|
|
}
|
|
};
|
|
|
|
if(!isProd) {
|
|
const conf = await ViteExpress.getViteConfig();
|
|
viteExpressOptions.inlineViteConfig = {
|
|
...viteExpressOptions.inlineViteConfig,
|
|
...conf
|
|
};
|
|
}
|
|
|
|
ViteExpress.config(viteExpressOptions);
|
|
try {
|
|
ViteExpress.listen(app, port, () => {
|
|
const start = stripIndents`\n
|
|
Server started:
|
|
${addresses.join('\n')}${dockerHint !== '' ? `\n${dockerHint}` : ''}`
|
|
|
|
logger.info(start);
|
|
|
|
if(localDefined) {
|
|
logger.info(`User-defined base URL for UI and redirect URLs (spotify, deezer, lastfm): ${local}`)
|
|
}
|
|
}).on('error', (err) => {
|
|
throw new Error('Server encountered unrecoverable error', {cause: err});
|
|
});
|
|
} catch (e) {
|
|
throw new Error('Server encountered unrecoverable error', {cause: e});
|
|
}
|
|
|
|
} catch (e) {
|
|
throw new Error('Server crashed with uncaught exception', {cause: e});
|
|
}
|
|
}
|
|
|
|
type ViteConfig = {
|
|
root: string;
|
|
base: string;
|
|
build: {
|
|
outDir: string;
|
|
};
|
|
server?: {
|
|
hmr?: boolean;
|
|
};
|
|
}; |