mirror of
https://github.com/zadam/trilium.git
synced 2025-11-12 08:15:52 +01:00
chore(nx/server): move source code
This commit is contained in:
83
apps/server/src/routes/custom.ts
Normal file
83
apps/server/src/routes/custom.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import log from "../services/log.js";
|
||||
import fileService from "./api/files.js";
|
||||
import scriptService from "../services/script.js";
|
||||
import cls from "../services/cls.js";
|
||||
import sql from "../services/sql.js";
|
||||
import becca from "../becca/becca.js";
|
||||
import type { Request, Response, Router } from "express";
|
||||
import { safeExtractMessageAndStackFromError } from "../services/utils.js";
|
||||
|
||||
function handleRequest(req: Request, res: Response) {
|
||||
// express puts content after first slash into 0 index element
|
||||
|
||||
const path = req.params.path + req.params[0];
|
||||
|
||||
const attributeIds = sql.getColumn<string>("SELECT attributeId FROM attributes WHERE isDeleted = 0 AND type = 'label' AND name IN ('customRequestHandler', 'customResourceProvider')");
|
||||
|
||||
const attrs = attributeIds.map((attrId) => becca.getAttribute(attrId));
|
||||
|
||||
for (const attr of attrs) {
|
||||
if (!attr?.value.trim()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const regex = new RegExp(`^${attr.value}$`);
|
||||
let match;
|
||||
|
||||
try {
|
||||
match = path.match(regex);
|
||||
} catch (e: unknown) {
|
||||
const [errMessage, errStack] = safeExtractMessageAndStackFromError(e);
|
||||
log.error(`Testing path for label '${attr.attributeId}', regex '${attr.value}' failed with error: ${errMessage}, stack: ${errStack}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (attr.name === "customRequestHandler") {
|
||||
const note = attr.getNote();
|
||||
|
||||
log.info(`Handling custom request '${path}' with note '${note.noteId}'`);
|
||||
|
||||
try {
|
||||
scriptService.executeNote(note, {
|
||||
pathParams: match.slice(1),
|
||||
req,
|
||||
res
|
||||
});
|
||||
} catch (e: unknown) {
|
||||
const [errMessage, errStack] = safeExtractMessageAndStackFromError(e);
|
||||
log.error(`Custom handler '${note.noteId}' failed with: ${errMessage}, ${errStack}`);
|
||||
res.setHeader("Content-Type", "text/plain").status(500).send(errMessage);
|
||||
}
|
||||
} else if (attr.name === "customResourceProvider") {
|
||||
fileService.downloadNoteInt(attr.noteId, res);
|
||||
} else {
|
||||
throw new Error(`Unrecognized attribute name '${attr.name}'`);
|
||||
}
|
||||
|
||||
return; // only the first handler is executed
|
||||
}
|
||||
|
||||
const message = `No handler matched for custom '${path}' request.`;
|
||||
|
||||
log.info(message);
|
||||
res.setHeader("Content-Type", "text/plain").status(404).send(message);
|
||||
}
|
||||
|
||||
function register(router: Router) {
|
||||
// explicitly no CSRF middleware since it's meant to allow integration from external services
|
||||
|
||||
router.all("/custom/:path*", (req: Request, res: Response, _next) => {
|
||||
cls.namespace.bindEmitter(req);
|
||||
cls.namespace.bindEmitter(res);
|
||||
|
||||
cls.init(() => handleRequest(req, res));
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
register
|
||||
};
|
||||
Reference in New Issue
Block a user