chore(monorepo/server): remove top-level await completely

This commit is contained in:
Elian Doran 2025-04-22 19:47:27 +03:00
parent 6e35806340
commit 6543d6c362
No known key found for this signature in database
9 changed files with 123 additions and 142 deletions

View File

@ -2,7 +2,6 @@
"name": "@triliumnext/server",
"version": "0.0.1",
"private": true,
"type": "module",
"dependencies": {
"express": "4.21.2",
"express-openid-connect": "^2.17.1",

View File

@ -20,19 +20,19 @@ import openID from "./services/open_id.js";
import { t } from "i18next";
import eventService from "./services/events.js";
import log from "./services/log.js";
import "./services/handlers.js";
import "./becca/becca_loader.js";
await import("./services/handlers.js");
await import("./becca/becca_loader.js");
export default async function buildApp() {
const app = express();
const app = express();
const scriptDir = dirname(fileURLToPath(import.meta.url));
const scriptDir = dirname(fileURLToPath(import.meta.url));
// Initialize DB
sql_init.initializeDb();
// Initialize DB
sql_init.initializeDb();
// Listen for database initialization event
eventService.subscribe(eventService.DB_INITIALIZED, async () => {
// Listen for database initialization event
eventService.subscribe(eventService.DB_INITIALIZED, async () => {
try {
log.info("Database initialized, setting up LLM features");
@ -48,10 +48,10 @@ eventService.subscribe(eventService.DB_INITIALIZED, async () => {
} catch (error) {
console.error("Error initializing LLM features:", error);
}
});
});
// Initialize LLM features only if database is already initialized
if (sql_init.isDbInitialized()) {
// Initialize LLM features only if database is already initialized
if (sql_init.isDbInitialized()) {
try {
// Initialize embedding providers
const { initializeEmbeddings } = await import("./services/llm/embeddings/init.js");
@ -63,15 +63,15 @@ if (sql_init.isDbInitialized()) {
} catch (error) {
console.error("Error initializing LLM features:", error);
}
} else {
} else {
console.log("Database not initialized yet. LLM features will be initialized after setup.");
}
}
// view engine setup
app.set("views", path.join(scriptDir, "views"));
app.set("view engine", "ejs");
// view engine setup
app.set("views", path.join(scriptDir, "views"));
app.set("view engine", "ejs");
app.use((req, res, next) => {
app.use((req, res, next) => {
// set CORS header
if (config["Network"]["corsAllowOrigin"]) {
res.header("Access-Control-Allow-Origin", config["Network"]["corsAllowOrigin"]);
@ -85,55 +85,56 @@ app.use((req, res, next) => {
res.locals.t = t;
return next();
});
});
if (!utils.isElectron) {
if (!utils.isElectron) {
app.use(compression()); // HTTP compression
}
}
app.use(
app.use(
helmet({
hidePoweredBy: false, // errors out in electron
contentSecurityPolicy: false,
crossOriginEmbedderPolicy: false
})
);
);
app.use(express.text({ limit: "500mb" }));
app.use(express.json({ limit: "500mb" }));
app.use(express.raw({ limit: "500mb" }));
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(scriptDir, "public/root")));
app.use(`/manifest.webmanifest`, express.static(path.join(scriptDir, "public/manifest.webmanifest")));
app.use(`/robots.txt`, express.static(path.join(scriptDir, "public/robots.txt")));
app.use(`/icon.png`, express.static(path.join(scriptDir, "public/icon.png")));
app.use(sessionParser);
app.use(favicon(`${scriptDir}/../assets/icon.ico`));
app.use(express.text({ limit: "500mb" }));
app.use(express.json({ limit: "500mb" }));
app.use(express.raw({ limit: "500mb" }));
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(scriptDir, "public/root")));
app.use(`/manifest.webmanifest`, express.static(path.join(scriptDir, "public/manifest.webmanifest")));
app.use(`/robots.txt`, express.static(path.join(scriptDir, "public/robots.txt")));
app.use(`/icon.png`, express.static(path.join(scriptDir, "public/icon.png")));
app.use(sessionParser);
app.use(favicon(`${scriptDir}/../assets/icon.ico`));
if (openID.isOpenIDEnabled())
if (openID.isOpenIDEnabled())
app.use(auth(openID.generateOAuthConfig()));
await assets.register(app);
routes.register(app);
custom.register(app);
error_handlers.register(app);
await assets.register(app);
routes.register(app);
custom.register(app);
error_handlers.register(app);
// triggers sync timer
await import("./services/sync.js");
// triggers sync timer
await import("./services/sync.js");
// triggers backup timer
await import("./services/backup.js");
// triggers backup timer
await import("./services/backup.js");
// trigger consistency checks timer
await import("./services/consistency_checks.js");
// trigger consistency checks timer
await import("./services/consistency_checks.js");
await import("./services/scheduler.js");
await import("./services/scheduler.js");
startScheduledCleanup();
startScheduledCleanup();
if (utils.isElectron) {
if (utils.isElectron) {
(await import("@electron/remote/main/index.js")).initialize();
}
}
export default app;
return app;
}

View File

@ -6,8 +6,8 @@
import { initializeTranslations } from "./services/i18n.js";
async function startApplication() {
await initializeTranslations();
await import("./www.js");
}
await initializeTranslations();
await startApplication();
startApplication();

View File

@ -1,16 +1,17 @@
import type { Application } from "express";
import swaggerUi from "swagger-ui-express";
import { readFile } from "fs/promises";
import { fileURLToPath } from "url";
import { dirname, join } from "path";
import yaml from "js-yaml";
import type { JsonObject } from "swagger-ui-express";
import { readFileSync } from "fs";
const __dirname = dirname(fileURLToPath(import.meta.url));
const etapiDocument = yaml.load(await readFile(join(__dirname, "../etapi/etapi.openapi.yaml"), "utf8")) as JsonObject;
const apiDocument = JSON.parse(await readFile(join(__dirname, "api", "openapi.json"), "utf-8"));
function register(app: Application) {
export default function register(app: Application) {
const etapiDocument = yaml.load(readFileSync(join(__dirname, "../etapi/etapi.openapi.yaml"), "utf8")) as JsonObject;
const apiDocument = JSON.parse(readFileSync(join(__dirname, "api", "openapi.json"), "utf-8"));
app.use(
"/etapi/docs/",
swaggerUi.serveFiles(etapiDocument),
@ -29,7 +30,3 @@ function register(app: Application) {
})
);
}
export default {
register
};

View File

@ -1,5 +1,4 @@
import { ipcMain } from "electron";
import type { Application } from "express";
interface Response {
statusCode: number;
@ -10,7 +9,7 @@ interface Response {
send: (obj: {}) => void; // eslint-disable-line @typescript-eslint/no-empty-object-type
}
function init(app: Application) {
function init(app: Express.Application) {
ipcMain.on("server-request", (event, arg) => {
const req = {
url: arg.url,

View File

@ -12,19 +12,6 @@ import AbstractBeccaEntity from "../becca/entities/abstract_becca_entity.js";
import type { IncomingMessage, Server as HttpServer } from "http";
import type { EntityChange } from "./entity_changes_interface.js";
if (isDev) {
const chokidar = (await import("chokidar")).default;
const debounce = (await import("debounce")).default;
const debouncedReloadFrontend = debounce(() => reloadFrontend("source code change"), 200);
chokidar
.watch("src/public", {
ignored: "src/public/app/doc_notes/en/User Guide"
})
.on("add", debouncedReloadFrontend)
.on("change", debouncedReloadFrontend)
.on("unlink", debouncedReloadFrontend);
}
let webSocketServer!: WebSocketServer;
let lastSyncedPush: number | null = null;

View File

@ -1,6 +1,5 @@
#!/usr/bin/env node
import app from "./app.js";
import sessionParser from "./routes/session_parser.js";
import fs from "fs";
import http from "http";
@ -13,6 +12,8 @@ import ws from "./services/ws.js";
import utils from "./services/utils.js";
import port from "./services/port.js";
import host from "./services/host.js";
import buildApp from "./app.js";
import type { Express } from "express";
const MINIMUM_NODE_VERSION = "20.0.0";
@ -47,6 +48,8 @@ tmp.setGracefulCleanup();
startTrilium();
async function startTrilium() {
const app = await buildApp();
/**
* The intended behavior is to detect when a second instance is running, in that case open the old instance
* instead of the new one. This is complicated by the fact that it is possible to run multiple instances of Trilium
@ -74,7 +77,7 @@ async function startTrilium() {
log.info(`CPU model: ${cpuModel}, logical cores: ${cpuInfos.length}, freq: ${cpuInfos[0].speed} Mhz`);
}
const httpServer = startHttpServer();
const httpServer = startHttpServer(app);
ws.init(httpServer, sessionParser as any); // TODO: Not sure why session parser is incompatible.
@ -84,7 +87,7 @@ async function startTrilium() {
}
}
function startHttpServer() {
function startHttpServer(app: Express) {
app.set("port", port);
app.set("host", host);

View File

@ -1,9 +1,8 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "ESNext",
"target": "ESNext",
"moduleResolution": "bundler",
"module": "NodeNext",
"moduleResolution": "nodenext",
"outDir": "dist",
"types": [
"node",

View File

@ -3,8 +3,7 @@ const { join } = require('path');
module.exports = {
output: {
path: join(__dirname, 'dist'),
libraryTarget: "module"
path: join(__dirname, 'dist')
},
plugins: [
new NxAppWebpackPlugin({
@ -17,8 +16,5 @@ module.exports = {
outputHashing: 'none',
generatePackageJson: true,
})
],
experiments: {
outputModule: true
}
]
};