mirror of
https://github.com/zadam/trilium.git
synced 2026-02-28 09:33:38 +01:00
refactor(server): use strong typing for routes
This commit is contained in:
parent
fd805a5279
commit
0c6326b678
@ -1,14 +1,15 @@
|
||||
import type { AttachmentRow } from "@triliumnext/commons";
|
||||
import type { Router } from "express";
|
||||
|
||||
import becca from "../becca/becca.js";
|
||||
import utils from "../services/utils.js";
|
||||
import eu from "./etapi_utils.js";
|
||||
import type { ValidatorMap } from "./etapi-interface.js";
|
||||
import mappers from "./mappers.js";
|
||||
import v from "./validators.js";
|
||||
import utils from "../services/utils.js";
|
||||
import type { Router } from "express";
|
||||
import type { AttachmentRow } from "@triliumnext/commons";
|
||||
import type { ValidatorMap } from "./etapi-interface.js";
|
||||
|
||||
function register(router: Router) {
|
||||
eu.route(router, "get", "/etapi/notes/:noteId/attachments", (req, res, next) => {
|
||||
eu.route<{ noteId: string }>(router, "get", "/etapi/notes/:noteId/attachments", (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
const attachments = note.getAttachments();
|
||||
res.json(attachments.map((attachment) => mappers.mapAttachmentToPojo(attachment)));
|
||||
@ -23,7 +24,7 @@ function register(router: Router) {
|
||||
content: [v.isString]
|
||||
};
|
||||
|
||||
eu.route(router, "post", "/etapi/attachments", (req, res, next) => {
|
||||
eu.route<{ attachmentId: string }>(router, "post", "/etapi/attachments", (req, res, next) => {
|
||||
const _params: Partial<AttachmentRow> = {};
|
||||
eu.validateAndPatch(_params, req.body, ALLOWED_PROPERTIES_FOR_CREATE_ATTACHMENT);
|
||||
const params = _params as AttachmentRow;
|
||||
@ -41,7 +42,7 @@ function register(router: Router) {
|
||||
}
|
||||
});
|
||||
|
||||
eu.route(router, "get", "/etapi/attachments/:attachmentId", (req, res, next) => {
|
||||
eu.route<{ attachmentId: string }>(router, "get", "/etapi/attachments/:attachmentId", (req, res, next) => {
|
||||
const attachment = eu.getAndCheckAttachment(req.params.attachmentId);
|
||||
|
||||
res.json(mappers.mapAttachmentToPojo(attachment));
|
||||
@ -54,7 +55,7 @@ function register(router: Router) {
|
||||
position: [v.notNull, v.isInteger]
|
||||
};
|
||||
|
||||
eu.route(router, "patch", "/etapi/attachments/:attachmentId", (req, res, next) => {
|
||||
eu.route<{ attachmentId: string }>(router, "patch", "/etapi/attachments/:attachmentId", (req, res, next) => {
|
||||
const attachment = eu.getAndCheckAttachment(req.params.attachmentId);
|
||||
|
||||
if (attachment.isProtected) {
|
||||
@ -67,7 +68,7 @@ function register(router: Router) {
|
||||
res.json(mappers.mapAttachmentToPojo(attachment));
|
||||
});
|
||||
|
||||
eu.route(router, "get", "/etapi/attachments/:attachmentId/content", (req, res, next) => {
|
||||
eu.route<{ attachmentId: string }>(router, "get", "/etapi/attachments/:attachmentId/content", (req, res, next) => {
|
||||
const attachment = eu.getAndCheckAttachment(req.params.attachmentId);
|
||||
|
||||
if (attachment.isProtected) {
|
||||
@ -84,7 +85,7 @@ function register(router: Router) {
|
||||
res.send(attachment.getContent());
|
||||
});
|
||||
|
||||
eu.route(router, "put", "/etapi/attachments/:attachmentId/content", (req, res, next) => {
|
||||
eu.route<{ attachmentId: string }>(router, "put", "/etapi/attachments/:attachmentId/content", (req, res, next) => {
|
||||
const attachment = eu.getAndCheckAttachment(req.params.attachmentId);
|
||||
|
||||
if (attachment.isProtected) {
|
||||
@ -96,7 +97,7 @@ function register(router: Router) {
|
||||
return res.sendStatus(204);
|
||||
});
|
||||
|
||||
eu.route(router, "delete", "/etapi/attachments/:attachmentId", (req, res, next) => {
|
||||
eu.route<{ attachmentId: string }>(router, "delete", "/etapi/attachments/:attachmentId", (req, res, next) => {
|
||||
const attachment = becca.getAttachment(req.params.attachmentId);
|
||||
|
||||
if (!attachment) {
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
import becca from "../becca/becca.js";
|
||||
import eu from "./etapi_utils.js";
|
||||
import mappers from "./mappers.js";
|
||||
import attributeService from "../services/attributes.js";
|
||||
import v from "./validators.js";
|
||||
import type { Router } from "express";
|
||||
import type { AttributeRow } from "@triliumnext/commons";
|
||||
import type { Router } from "express";
|
||||
|
||||
import becca from "../becca/becca.js";
|
||||
import attributeService from "../services/attributes.js";
|
||||
import eu from "./etapi_utils.js";
|
||||
import type { ValidatorMap } from "./etapi-interface.js";
|
||||
import mappers from "./mappers.js";
|
||||
import v from "./validators.js";
|
||||
|
||||
function register(router: Router) {
|
||||
eu.route(router, "get", "/etapi/attributes/:attributeId", (req, res, next) => {
|
||||
eu.route<{ attributeId: string }>(router, "get", "/etapi/attributes/:attributeId", (req, res, next) => {
|
||||
const attribute = eu.getAndCheckAttribute(req.params.attributeId);
|
||||
|
||||
res.json(mappers.mapAttributeToPojo(attribute));
|
||||
@ -51,7 +52,7 @@ function register(router: Router) {
|
||||
position: [v.notNull, v.isInteger]
|
||||
};
|
||||
|
||||
eu.route(router, "patch", "/etapi/attributes/:attributeId", (req, res, next) => {
|
||||
eu.route<{ attributeId: string }>(router, "patch", "/etapi/attributes/:attributeId", (req, res, next) => {
|
||||
const attribute = eu.getAndCheckAttribute(req.params.attributeId);
|
||||
|
||||
if (attribute.type === "label") {
|
||||
@ -67,7 +68,7 @@ function register(router: Router) {
|
||||
res.json(mappers.mapAttributeToPojo(attribute));
|
||||
});
|
||||
|
||||
eu.route(router, "delete", "/etapi/attributes/:attributeId", (req, res, next) => {
|
||||
eu.route<{ attributeId: string }>(router, "delete", "/etapi/attributes/:attributeId", (req, res, next) => {
|
||||
const attribute = becca.getAttribute(req.params.attributeId);
|
||||
|
||||
if (!attribute) {
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import type { Router } from "express";
|
||||
|
||||
import eu from "./etapi_utils.js";
|
||||
import backupService from "../services/backup.js";
|
||||
import eu from "./etapi_utils.js";
|
||||
|
||||
function register(router: Router) {
|
||||
eu.route(router, "put", "/etapi/backup/:backupName", (req, res, next) => {
|
||||
eu.route<{ backupName: string }>(router, "put", "/etapi/backup/:backupName", (req, res, next) => {
|
||||
backupService.backupNow(req.params.backupName)
|
||||
.then(() => res.sendStatus(204))
|
||||
.catch(() => res.sendStatus(500));
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import type { BranchRow } from "@triliumnext/commons";
|
||||
import type { Router } from "express";
|
||||
|
||||
import becca from "../becca/becca.js";
|
||||
import eu from "./etapi_utils.js";
|
||||
import mappers from "./mappers.js";
|
||||
import BBranch from "../becca/entities/bbranch.js";
|
||||
import entityChangesService from "../services/entity_changes.js";
|
||||
import eu from "./etapi_utils.js";
|
||||
import mappers from "./mappers.js";
|
||||
import v from "./validators.js";
|
||||
import type { BranchRow } from "@triliumnext/commons";
|
||||
|
||||
function register(router: Router) {
|
||||
eu.route(router, "get", "/etapi/branches/:branchId", (req, res, next) => {
|
||||
eu.route<{ branchId: string }>(router, "get", "/etapi/branches/:branchId", (req, res, next) => {
|
||||
const branch = eu.getAndCheckBranch(req.params.branchId);
|
||||
|
||||
res.json(mappers.mapBranchToPojo(branch));
|
||||
@ -37,15 +37,15 @@ function register(router: Router) {
|
||||
existing.save();
|
||||
|
||||
return res.status(200).json(mappers.mapBranchToPojo(existing));
|
||||
} else {
|
||||
try {
|
||||
const branch = new BBranch(params).save();
|
||||
}
|
||||
try {
|
||||
const branch = new BBranch(params).save();
|
||||
|
||||
res.status(201).json(mappers.mapBranchToPojo(branch));
|
||||
} catch (e: any) {
|
||||
throw new eu.EtapiError(400, eu.GENERIC_CODE, e.message);
|
||||
}
|
||||
res.status(201).json(mappers.mapBranchToPojo(branch));
|
||||
} catch (e: any) {
|
||||
throw new eu.EtapiError(400, eu.GENERIC_CODE, e.message);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
const ALLOWED_PROPERTIES_FOR_PATCH = {
|
||||
@ -54,7 +54,7 @@ function register(router: Router) {
|
||||
isExpanded: [v.notNull, v.isBoolean]
|
||||
};
|
||||
|
||||
eu.route(router, "patch", "/etapi/branches/:branchId", (req, res, next) => {
|
||||
eu.route<{ branchId: string }>(router, "patch", "/etapi/branches/:branchId", (req, res, next) => {
|
||||
const branch = eu.getAndCheckBranch(req.params.branchId);
|
||||
|
||||
eu.validateAndPatch(branch, req.body, ALLOWED_PROPERTIES_FOR_PATCH);
|
||||
@ -63,7 +63,7 @@ function register(router: Router) {
|
||||
res.json(mappers.mapBranchToPojo(branch));
|
||||
});
|
||||
|
||||
eu.route(router, "delete", "/etapi/branches/:branchId", (req, res, next) => {
|
||||
eu.route<{ branchId: string }>(router, "delete", "/etapi/branches/:branchId", (req, res, next) => {
|
||||
const branch = becca.getBranch(req.params.branchId);
|
||||
|
||||
if (!branch) {
|
||||
@ -75,7 +75,7 @@ function register(router: Router) {
|
||||
res.sendStatus(204);
|
||||
});
|
||||
|
||||
eu.route(router, "post", "/etapi/refresh-note-ordering/:parentNoteId", (req, res, next) => {
|
||||
eu.route<{ parentNoteId: string }>(router, "post", "/etapi/refresh-note-ordering/:parentNoteId", (req, res, next) => {
|
||||
eu.getAndCheckNote(req.params.parentNoteId);
|
||||
|
||||
entityChangesService.putNoteReorderingEntityChange(req.params.parentNoteId, "etapi");
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import cls from "../services/cls.js";
|
||||
import sql from "../services/sql.js";
|
||||
import log from "../services/log.js";
|
||||
import becca from "../becca/becca.js";
|
||||
import etapiTokenService from "../services/etapi_tokens.js";
|
||||
import config from "../services/config.js";
|
||||
import type { NextFunction, Request, RequestHandler, Response, Router } from "express";
|
||||
import type { ValidatorMap } from "./etapi-interface.js";
|
||||
import type { ParamsDictionary } from "express-serve-static-core";
|
||||
|
||||
import becca from "../becca/becca.js";
|
||||
import type { ApiRequestHandler, SyncRouteRequestHandler } from "../routes/route_api.js";
|
||||
import cls from "../services/cls.js";
|
||||
import config from "../services/config.js";
|
||||
import etapiTokenService from "../services/etapi_tokens.js";
|
||||
import log from "../services/log.js";
|
||||
import sql from "../services/sql.js";
|
||||
import type { ValidatorMap } from "./etapi-interface.js";
|
||||
const GENERIC_CODE = "GENERIC";
|
||||
|
||||
type HttpMethod = "all" | "get" | "post" | "put" | "delete" | "patch" | "options" | "head";
|
||||
@ -35,8 +37,8 @@ function sendError(res: Response, statusCode: number, code: string, message: str
|
||||
.send(
|
||||
JSON.stringify({
|
||||
status: statusCode,
|
||||
code: code,
|
||||
message: message
|
||||
code,
|
||||
message
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -49,7 +51,7 @@ function checkEtapiAuth(req: Request, res: Response, next: NextFunction) {
|
||||
}
|
||||
}
|
||||
|
||||
function processRequest(req: Request, res: Response, routeHandler: ApiRequestHandler, next: NextFunction, method: string, path: string) {
|
||||
function processRequest<P extends ParamsDictionary>(req: Request<P>, res: Response, routeHandler: ApiRequestHandler<P>, next: NextFunction, method: string, path: string) {
|
||||
try {
|
||||
cls.namespace.bindEmitter(req);
|
||||
cls.namespace.bindEmitter(res);
|
||||
@ -73,12 +75,12 @@ function processRequest(req: Request, res: Response, routeHandler: ApiRequestHan
|
||||
}
|
||||
}
|
||||
|
||||
function route(router: Router, method: HttpMethod, path: string, routeHandler: SyncRouteRequestHandler) {
|
||||
router[method](path, checkEtapiAuth, (req: Request, res: Response, next: NextFunction) => processRequest(req, res, routeHandler, next, method, path));
|
||||
function route<P extends ParamsDictionary>(router: Router, method: HttpMethod, path: string, routeHandler: SyncRouteRequestHandler<P>) {
|
||||
router[method](path, checkEtapiAuth, (req: Request<P>, res: Response, next: NextFunction) => processRequest(req, res, routeHandler, next, method, path));
|
||||
}
|
||||
|
||||
function NOT_AUTHENTICATED_ROUTE(router: Router, method: HttpMethod, path: string, middleware: RequestHandler[], routeHandler: SyncRouteRequestHandler) {
|
||||
router[method](path, ...middleware, (req: Request, res: Response, next: NextFunction) => processRequest(req, res, routeHandler, next, method, path));
|
||||
function NOT_AUTHENTICATED_ROUTE<P extends ParamsDictionary>(router: Router, method: HttpMethod, path: string, middleware: RequestHandler[], routeHandler: SyncRouteRequestHandler<P>) {
|
||||
router[method](path, ...middleware, (req: Request<P>, res: Response, next: NextFunction) => processRequest(req, res, routeHandler, next, method, path));
|
||||
}
|
||||
|
||||
function getAndCheckNote(noteId: string) {
|
||||
@ -86,9 +88,8 @@ function getAndCheckNote(noteId: string) {
|
||||
|
||||
if (note) {
|
||||
return note;
|
||||
} else {
|
||||
throw new EtapiError(404, "NOTE_NOT_FOUND", `Note '${noteId}' not found.`);
|
||||
}
|
||||
throw new EtapiError(404, "NOTE_NOT_FOUND", `Note '${noteId}' not found.`);
|
||||
}
|
||||
|
||||
function getAndCheckAttachment(attachmentId: string) {
|
||||
@ -96,9 +97,9 @@ function getAndCheckAttachment(attachmentId: string) {
|
||||
|
||||
if (attachment) {
|
||||
return attachment;
|
||||
} else {
|
||||
throw new EtapiError(404, "ATTACHMENT_NOT_FOUND", `Attachment '${attachmentId}' not found.`);
|
||||
}
|
||||
throw new EtapiError(404, "ATTACHMENT_NOT_FOUND", `Attachment '${attachmentId}' not found.`);
|
||||
|
||||
}
|
||||
|
||||
function getAndCheckBranch(branchId: string) {
|
||||
@ -106,9 +107,8 @@ function getAndCheckBranch(branchId: string) {
|
||||
|
||||
if (branch) {
|
||||
return branch;
|
||||
} else {
|
||||
throw new EtapiError(404, "BRANCH_NOT_FOUND", `Branch '${branchId}' not found.`);
|
||||
}
|
||||
throw new EtapiError(404, "BRANCH_NOT_FOUND", `Branch '${branchId}' not found.`);
|
||||
}
|
||||
|
||||
function getAndCheckAttribute(attributeId: string) {
|
||||
@ -116,9 +116,8 @@ function getAndCheckAttribute(attributeId: string) {
|
||||
|
||||
if (attribute) {
|
||||
return attribute;
|
||||
} else {
|
||||
throw new EtapiError(404, "ATTRIBUTE_NOT_FOUND", `Attribute '${attributeId}' not found.`);
|
||||
}
|
||||
throw new EtapiError(404, "ATTRIBUTE_NOT_FOUND", `Attribute '${attributeId}' not found.`);
|
||||
}
|
||||
|
||||
function getAndCheckRevision(revisionId: string) {
|
||||
@ -126,9 +125,8 @@ function getAndCheckRevision(revisionId: string) {
|
||||
|
||||
if (revision) {
|
||||
return revision;
|
||||
} else {
|
||||
throw new EtapiError(404, "REVISION_NOT_FOUND", `Revision '${revisionId}' not found.`);
|
||||
}
|
||||
throw new EtapiError(404, "REVISION_NOT_FOUND", `Revision '${revisionId}' not found.`);
|
||||
}
|
||||
|
||||
function validateAndPatch(target: any, source: any, allowedProperties: ValidatorMap) {
|
||||
|
||||
@ -1,20 +1,21 @@
|
||||
import becca from "../becca/becca.js";
|
||||
import utils from "../services/utils.js";
|
||||
import eu from "./etapi_utils.js";
|
||||
import mappers from "./mappers.js";
|
||||
import noteService from "../services/notes.js";
|
||||
import TaskContext from "../services/task_context.js";
|
||||
import v from "./validators.js";
|
||||
import searchService from "../services/search/services/search.js";
|
||||
import SearchContext from "../services/search/search_context.js";
|
||||
import zipExportService from "../services/export/zip.js";
|
||||
import zipImportService from "../services/import/zip.js";
|
||||
import type { Request, Router } from "express";
|
||||
import type { ParsedQs } from "qs";
|
||||
import type { NoteParams } from "../services/note-interface.js";
|
||||
import type { SearchParams } from "../services/search/services/types.js";
|
||||
import type { ValidatorMap } from "./etapi-interface.js";
|
||||
|
||||
import becca from "../becca/becca.js";
|
||||
import zipExportService from "../services/export/zip.js";
|
||||
import type { ExportFormat } from "../services/export/zip/abstract_provider.js";
|
||||
import zipImportService from "../services/import/zip.js";
|
||||
import type { NoteParams } from "../services/note-interface.js";
|
||||
import noteService from "../services/notes.js";
|
||||
import SearchContext from "../services/search/search_context.js";
|
||||
import searchService from "../services/search/services/search.js";
|
||||
import type { SearchParams } from "../services/search/services/types.js";
|
||||
import TaskContext from "../services/task_context.js";
|
||||
import utils from "../services/utils.js";
|
||||
import eu from "./etapi_utils.js";
|
||||
import type { ValidatorMap } from "./etapi-interface.js";
|
||||
import mappers from "./mappers.js";
|
||||
import v from "./validators.js";
|
||||
|
||||
function register(router: Router) {
|
||||
eu.route(router, "get", "/etapi/notes", (req, res, next) => {
|
||||
@ -41,7 +42,7 @@ function register(router: Router) {
|
||||
res.json(resp);
|
||||
});
|
||||
|
||||
eu.route(router, "get", "/etapi/notes/:noteId", (req, res, next) => {
|
||||
eu.route<{ noteId: string }>(router, "get", "/etapi/notes/:noteId", (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
|
||||
res.json(mappers.mapNoteToPojo(note));
|
||||
@ -86,7 +87,7 @@ function register(router: Router) {
|
||||
utcDateCreated: [v.notNull, v.isString, v.isUtcDateTime]
|
||||
};
|
||||
|
||||
eu.route(router, "patch", "/etapi/notes/:noteId", (req, res, next) => {
|
||||
eu.route<{ noteId: string }>(router, "patch", "/etapi/notes/:noteId", (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
|
||||
if (note.isProtected) {
|
||||
@ -100,7 +101,7 @@ function register(router: Router) {
|
||||
res.json(mappers.mapNoteToPojo(note));
|
||||
});
|
||||
|
||||
eu.route(router, "delete", "/etapi/notes/:noteId", (req, res, next) => {
|
||||
eu.route<{ noteId: string }>(router, "delete", "/etapi/notes/:noteId", (req, res, next) => {
|
||||
const { noteId } = req.params;
|
||||
|
||||
const note = becca.getNote(noteId);
|
||||
@ -114,7 +115,7 @@ function register(router: Router) {
|
||||
res.sendStatus(204);
|
||||
});
|
||||
|
||||
eu.route(router, "get", "/etapi/notes/:noteId/content", (req, res, next) => {
|
||||
eu.route<{ noteId: string }>(router, "get", "/etapi/notes/:noteId/content", (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
|
||||
if (note.isProtected) {
|
||||
@ -131,7 +132,7 @@ function register(router: Router) {
|
||||
res.send(note.getContent());
|
||||
});
|
||||
|
||||
eu.route(router, "put", "/etapi/notes/:noteId/content", (req, res, next) => {
|
||||
eu.route<{ noteId: string }>(router, "put", "/etapi/notes/:noteId/content", (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
|
||||
if (note.isProtected) {
|
||||
@ -146,7 +147,7 @@ function register(router: Router) {
|
||||
return res.sendStatus(204);
|
||||
});
|
||||
|
||||
eu.route(router, "get", "/etapi/notes/:noteId/export", (req, res, next) => {
|
||||
eu.route<{ noteId: string }>(router, "get", "/etapi/notes/:noteId/export", (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
const format = req.query.format || "html";
|
||||
|
||||
@ -163,7 +164,7 @@ function register(router: Router) {
|
||||
zipExportService.exportToZip(taskContext, branch, format as ExportFormat, res);
|
||||
});
|
||||
|
||||
eu.route(router, "post", "/etapi/notes/:noteId/import", (req, res, next) => {
|
||||
eu.route<{ noteId: string }>(router, "post", "/etapi/notes/:noteId/import", (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
const taskContext = new TaskContext("no-progress-reporting", "importNotes", null);
|
||||
|
||||
@ -175,7 +176,7 @@ function register(router: Router) {
|
||||
}); // we need better error handling here, async errors won't be properly processed.
|
||||
});
|
||||
|
||||
eu.route(router, "post", "/etapi/notes/:noteId/revision", (req, res, next) => {
|
||||
eu.route<{ noteId: string }>(router, "post", "/etapi/notes/:noteId/revision", (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
|
||||
note.saveRevision();
|
||||
@ -183,7 +184,7 @@ function register(router: Router) {
|
||||
return res.sendStatus(204);
|
||||
});
|
||||
|
||||
eu.route(router, "get", "/etapi/notes/:noteId/attachments", (req, res, next) => {
|
||||
eu.route<{ noteId: string }>(router, "get", "/etapi/notes/:noteId/attachments", (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
const attachments = note.getAttachments();
|
||||
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import type { NoteRow, RecentChangeRow } from "@triliumnext/commons";
|
||||
import type { Router } from "express";
|
||||
|
||||
import becca from "../becca/becca.js";
|
||||
import noteService from "../services/notes.js";
|
||||
import protectedSessionService from "../services/protected_session.js";
|
||||
import sql from "../services/sql.js";
|
||||
import TaskContext from "../services/task_context.js";
|
||||
import utils from "../services/utils.js";
|
||||
import eu from "./etapi_utils.js";
|
||||
import mappers from "./mappers.js";
|
||||
import noteService from "../services/notes.js";
|
||||
import TaskContext from "../services/task_context.js";
|
||||
import protectedSessionService from "../services/protected_session.js";
|
||||
import utils from "../services/utils.js";
|
||||
import type { Router } from "express";
|
||||
import type { NoteRow, RecentChangeRow } from "@triliumnext/commons";
|
||||
|
||||
function register(router: Router) {
|
||||
// GET /etapi/notes/history - must be registered before /etapi/notes/:noteId routes
|
||||
@ -130,7 +131,7 @@ function register(router: Router) {
|
||||
});
|
||||
|
||||
// GET /etapi/notes/:noteId/revisions - List all revisions for a note
|
||||
eu.route(router, "get", "/etapi/notes/:noteId/revisions", (req, res, next) => {
|
||||
eu.route<{ noteId: string }>(router, "get", "/etapi/notes/:noteId/revisions", (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
|
||||
const revisions = becca.getRevisionsFromQuery(
|
||||
@ -146,7 +147,7 @@ function register(router: Router) {
|
||||
});
|
||||
|
||||
// POST /etapi/notes/:noteId/undelete - Restore a deleted note
|
||||
eu.route(router, "post", "/etapi/notes/:noteId/undelete", (req, res, next) => {
|
||||
eu.route<{ noteId: string }>(router, "post", "/etapi/notes/:noteId/undelete", (req, res, next) => {
|
||||
const { noteId } = req.params;
|
||||
|
||||
const noteRow = sql.getRow<NoteRow | null>("SELECT * FROM notes WHERE noteId = ?", [noteId]);
|
||||
@ -172,7 +173,7 @@ function register(router: Router) {
|
||||
});
|
||||
|
||||
// GET /etapi/revisions/:revisionId - Get revision metadata
|
||||
eu.route(router, "get", "/etapi/revisions/:revisionId", (req, res, next) => {
|
||||
eu.route<{ revisionId: string }>(router, "get", "/etapi/revisions/:revisionId", (req, res, next) => {
|
||||
const revision = eu.getAndCheckRevision(req.params.revisionId);
|
||||
|
||||
if (revision.isProtected) {
|
||||
@ -183,7 +184,7 @@ function register(router: Router) {
|
||||
});
|
||||
|
||||
// GET /etapi/revisions/:revisionId/content - Get revision content
|
||||
eu.route(router, "get", "/etapi/revisions/:revisionId/content", (req, res, next) => {
|
||||
eu.route<{ revisionId: string }>(router, "get", "/etapi/revisions/:revisionId/content", (req, res, next) => {
|
||||
const revision = eu.getAndCheckRevision(req.params.revisionId);
|
||||
|
||||
if (revision.isProtected) {
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import specialNotesService from "../services/special_notes.js";
|
||||
import type { Router } from "express";
|
||||
|
||||
import dateNotesService from "../services/date_notes.js";
|
||||
import specialNotesService from "../services/special_notes.js";
|
||||
import eu from "./etapi_utils.js";
|
||||
import mappers from "./mappers.js";
|
||||
import type { Router } from "express";
|
||||
|
||||
const getDateInvalidError = (date: string) => new eu.EtapiError(400, "DATE_INVALID", `Date "${date}" is not valid.`);
|
||||
const getWeekInvalidError = (week: string) => new eu.EtapiError(400, "WEEK_INVALID", `Week "${week}" is not valid.`);
|
||||
@ -15,7 +16,7 @@ function isValidDate(date: string) {
|
||||
}
|
||||
|
||||
function register(router: Router) {
|
||||
eu.route(router, "get", "/etapi/inbox/:date", (req, res, next) => {
|
||||
eu.route<{ date: string }>(router, "get", "/etapi/inbox/:date", (req, res, next) => {
|
||||
const { date } = req.params;
|
||||
|
||||
if (!isValidDate(date)) {
|
||||
@ -25,7 +26,7 @@ function register(router: Router) {
|
||||
res.json(mappers.mapNoteToPojo(note));
|
||||
});
|
||||
|
||||
eu.route(router, "get", "/etapi/calendar/days/:date", (req, res, next) => {
|
||||
eu.route<{ date: string }>(router, "get", "/etapi/calendar/days/:date", (req, res, next) => {
|
||||
const { date } = req.params;
|
||||
|
||||
if (!isValidDate(date)) {
|
||||
@ -36,7 +37,7 @@ function register(router: Router) {
|
||||
res.json(mappers.mapNoteToPojo(note));
|
||||
});
|
||||
|
||||
eu.route(router, "get", "/etapi/calendar/week-first-day/:date", (req, res, next) => {
|
||||
eu.route<{ date: string }>(router, "get", "/etapi/calendar/week-first-day/:date", (req, res, next) => {
|
||||
const { date } = req.params;
|
||||
|
||||
if (!isValidDate(date)) {
|
||||
@ -47,7 +48,7 @@ function register(router: Router) {
|
||||
res.json(mappers.mapNoteToPojo(note));
|
||||
});
|
||||
|
||||
eu.route(router, "get", "/etapi/calendar/weeks/:week", (req, res, next) => {
|
||||
eu.route<{ week: string }>(router, "get", "/etapi/calendar/weeks/:week", (req, res, next) => {
|
||||
const { week } = req.params;
|
||||
|
||||
if (!/[0-9]{4}-W[0-9]{2}/.test(week)) {
|
||||
@ -63,7 +64,7 @@ function register(router: Router) {
|
||||
res.json(mappers.mapNoteToPojo(note));
|
||||
});
|
||||
|
||||
eu.route(router, "get", "/etapi/calendar/months/:month", (req, res, next) => {
|
||||
eu.route<{ month: string }>(router, "get", "/etapi/calendar/months/:month", (req, res, next) => {
|
||||
const { month } = req.params;
|
||||
|
||||
if (!/[0-9]{4}-[0-9]{2}/.test(month)) {
|
||||
@ -74,7 +75,7 @@ function register(router: Router) {
|
||||
res.json(mappers.mapNoteToPojo(note));
|
||||
});
|
||||
|
||||
eu.route(router, "get", "/etapi/calendar/years/:year", (req, res, next) => {
|
||||
eu.route<{ year: string }>(router, "get", "/etapi/calendar/years/:year", (req, res, next) => {
|
||||
const { year } = req.params;
|
||||
|
||||
if (!/[0-9]{4}/.test(year)) {
|
||||
|
||||
@ -1,29 +1,30 @@
|
||||
import becca from "../../becca/becca.js";
|
||||
import blobService from "../../services/blob.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import imageService from "../../services/image.js";
|
||||
import type { Request } from "express";
|
||||
import { ConvertAttachmentToNoteResponse } from "@triliumnext/commons";
|
||||
import type { Request } from "express";
|
||||
|
||||
function getAttachmentBlob(req: Request) {
|
||||
import becca from "../../becca/becca.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import blobService from "../../services/blob.js";
|
||||
import imageService from "../../services/image.js";
|
||||
|
||||
function getAttachmentBlob(req: Request<{ attachmentId: string }>) {
|
||||
const preview = req.query.preview === "true";
|
||||
|
||||
return blobService.getBlobPojo("attachments", req.params.attachmentId, { preview });
|
||||
}
|
||||
|
||||
function getAttachments(req: Request) {
|
||||
function getAttachments(req: Request<{ noteId: string }>) {
|
||||
const note = becca.getNoteOrThrow(req.params.noteId);
|
||||
|
||||
return note.getAttachments();
|
||||
}
|
||||
|
||||
function getAttachment(req: Request) {
|
||||
function getAttachment(req: Request<{ attachmentId: string }>) {
|
||||
const { attachmentId } = req.params;
|
||||
|
||||
return becca.getAttachmentOrThrow(attachmentId);
|
||||
}
|
||||
|
||||
function getAllAttachments(req: Request) {
|
||||
function getAllAttachments(req: Request<{ attachmentId: string }>) {
|
||||
const { attachmentId } = req.params;
|
||||
// one particular attachment is requested, but return all note's attachments
|
||||
|
||||
@ -31,10 +32,10 @@ function getAllAttachments(req: Request) {
|
||||
return attachment.getNote()?.getAttachments() || [];
|
||||
}
|
||||
|
||||
function saveAttachment(req: Request) {
|
||||
function saveAttachment(req: Request<{ noteId: string }>) {
|
||||
const { noteId } = req.params;
|
||||
const { attachmentId, role, mime, title, content } = req.body;
|
||||
const matchByQuery = req.query.matchBy
|
||||
const matchByQuery = req.query.matchBy;
|
||||
const isValidMatchBy = (typeof matchByQuery === "string") && (matchByQuery === "attachmentId" || matchByQuery === "title");
|
||||
const matchBy = isValidMatchBy ? matchByQuery : undefined;
|
||||
|
||||
@ -42,7 +43,7 @@ function saveAttachment(req: Request) {
|
||||
note.saveAttachment({ attachmentId, role, mime, title, content }, matchBy);
|
||||
}
|
||||
|
||||
function uploadAttachment(req: Request) {
|
||||
function uploadAttachment(req: Request<{ noteId: string }>) {
|
||||
const { noteId } = req.params;
|
||||
const { file } = req;
|
||||
|
||||
@ -76,7 +77,7 @@ function uploadAttachment(req: Request) {
|
||||
};
|
||||
}
|
||||
|
||||
function renameAttachment(req: Request) {
|
||||
function renameAttachment(req: Request<{ attachmentId: string }>) {
|
||||
const { title } = req.body;
|
||||
const { attachmentId } = req.params;
|
||||
|
||||
@ -90,7 +91,7 @@ function renameAttachment(req: Request) {
|
||||
attachment.save();
|
||||
}
|
||||
|
||||
function deleteAttachment(req: Request) {
|
||||
function deleteAttachment(req: Request<{ attachmentId: string }>) {
|
||||
const { attachmentId } = req.params;
|
||||
|
||||
const attachment = becca.getAttachment(attachmentId);
|
||||
@ -100,7 +101,7 @@ function deleteAttachment(req: Request) {
|
||||
}
|
||||
}
|
||||
|
||||
function convertAttachmentToNote(req: Request) {
|
||||
function convertAttachmentToNote(req: Request<{ attachmentId: string }>) {
|
||||
const { attachmentId } = req.params;
|
||||
|
||||
const attachment = becca.getAttachmentOrThrow(attachmentId);
|
||||
|
||||
@ -1,21 +1,22 @@
|
||||
"use strict";
|
||||
|
||||
import sql from "../../services/sql.js";
|
||||
import log from "../../services/log.js";
|
||||
import attributeService from "../../services/attributes.js";
|
||||
import BAttribute from "../../becca/entities/battribute.js";
|
||||
import becca from "../../becca/becca.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import type { Request } from "express";
|
||||
|
||||
import { UpdateAttributeResponse } from "@triliumnext/commons";
|
||||
import type { Request } from "express";
|
||||
|
||||
function getEffectiveNoteAttributes(req: Request) {
|
||||
import becca from "../../becca/becca.js";
|
||||
import BAttribute from "../../becca/entities/battribute.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import attributeService from "../../services/attributes.js";
|
||||
import log from "../../services/log.js";
|
||||
import sql from "../../services/sql.js";
|
||||
|
||||
function getEffectiveNoteAttributes(req: Request<{ noteId: string }>) {
|
||||
const note = becca.getNote(req.params.noteId);
|
||||
|
||||
return note?.getAttributes();
|
||||
}
|
||||
|
||||
function updateNoteAttribute(req: Request) {
|
||||
function updateNoteAttribute(req: Request<{ noteId: string }>) {
|
||||
const noteId = req.params.noteId;
|
||||
const body = req.body;
|
||||
|
||||
@ -47,7 +48,7 @@ function updateNoteAttribute(req: Request) {
|
||||
}
|
||||
|
||||
attribute = new BAttribute({
|
||||
noteId: noteId,
|
||||
noteId,
|
||||
name: body.name,
|
||||
type: body.type,
|
||||
isInheritable: body.isInheritable
|
||||
@ -96,7 +97,7 @@ function addNoteAttribute(req: Request) {
|
||||
new BAttribute({ ...body, noteId }).save();
|
||||
}
|
||||
|
||||
function deleteNoteAttribute(req: Request) {
|
||||
function deleteNoteAttribute(req: Request<{ noteId: string; attributeId: string }>) {
|
||||
const noteId = req.params.noteId;
|
||||
const attributeId = req.params.attributeId;
|
||||
|
||||
@ -111,7 +112,7 @@ function deleteNoteAttribute(req: Request) {
|
||||
}
|
||||
}
|
||||
|
||||
function updateNoteAttributes(req: Request) {
|
||||
function updateNoteAttributes(req: Request<{ noteId: string }>) {
|
||||
const noteId = req.params.noteId;
|
||||
const incomingAttributes = req.body;
|
||||
|
||||
@ -193,7 +194,7 @@ function getValuesForAttribute(req: Request) {
|
||||
return sql.getColumn("SELECT DISTINCT value FROM attributes WHERE isDeleted = 0 AND name = ? AND type = 'label' AND value != '' ORDER BY value", [attributeName]);
|
||||
}
|
||||
|
||||
function createRelation(req: Request) {
|
||||
function createRelation(req: Request<{ noteId: string; targetNoteId: string; name: string }>) {
|
||||
const sourceNoteId = req.params.noteId;
|
||||
const targetNoteId = req.params.targetNoteId;
|
||||
const name = req.params.name;
|
||||
@ -208,7 +209,7 @@ function createRelation(req: Request) {
|
||||
if (!attribute) {
|
||||
attribute = new BAttribute({
|
||||
noteId: sourceNoteId,
|
||||
name: name,
|
||||
name,
|
||||
type: "relation",
|
||||
value: targetNoteId
|
||||
}).save();
|
||||
|
||||
@ -1,24 +1,23 @@
|
||||
"use strict";
|
||||
|
||||
import sql from "../../services/sql.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import entityChangesService from "../../services/entity_changes.js";
|
||||
import treeService from "../../services/tree.js";
|
||||
import eraseService from "../../services/erase.js";
|
||||
import becca from "../../becca/becca.js";
|
||||
import TaskContext from "../../services/task_context.js";
|
||||
import branchService from "../../services/branches.js";
|
||||
import log from "../../services/log.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import eventService from "../../services/events.js";
|
||||
import type { Request } from "express";
|
||||
|
||||
import becca from "../../becca/becca.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import branchService from "../../services/branches.js";
|
||||
import entityChangesService from "../../services/entity_changes.js";
|
||||
import eraseService from "../../services/erase.js";
|
||||
import eventService from "../../services/events.js";
|
||||
import log from "../../services/log.js";
|
||||
import sql from "../../services/sql.js";
|
||||
import TaskContext from "../../services/task_context.js";
|
||||
import treeService from "../../services/tree.js";
|
||||
import utils from "../../services/utils.js";
|
||||
|
||||
/**
|
||||
* Code in this file deals with moving and cloning branches. The relationship between note and parent note is unique
|
||||
* for not deleted branches. There may be multiple deleted note-parent note relationships.
|
||||
*/
|
||||
|
||||
function moveBranchToParent(req: Request) {
|
||||
function moveBranchToParent(req: Request<{ branchId: string, parentBranchId: string }>) {
|
||||
const { branchId, parentBranchId } = req.params;
|
||||
|
||||
const branchToMove = becca.getBranch(branchId);
|
||||
@ -31,7 +30,7 @@ function moveBranchToParent(req: Request) {
|
||||
return branchService.moveBranchToBranch(branchToMove, targetParentBranch, branchId);
|
||||
}
|
||||
|
||||
function moveBranchBeforeNote(req: Request) {
|
||||
function moveBranchBeforeNote(req: Request<{ branchId: string, beforeBranchId: string }>) {
|
||||
const { branchId, beforeBranchId } = req.params;
|
||||
|
||||
const branchToMove = becca.getBranchOrThrow(branchId);
|
||||
@ -79,7 +78,7 @@ function moveBranchBeforeNote(req: Request) {
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
function moveBranchAfterNote(req: Request) {
|
||||
function moveBranchAfterNote(req: Request<{ branchId: string, afterBranchId: string }>) {
|
||||
const { branchId, afterBranchId } = req.params;
|
||||
|
||||
const branchToMove = becca.getBranchOrThrow(branchId);
|
||||
@ -128,7 +127,7 @@ function moveBranchAfterNote(req: Request) {
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
function setExpanded(req: Request) {
|
||||
function setExpanded(req: Request<{ branchId: string, expanded: string }>) {
|
||||
const { branchId } = req.params;
|
||||
const expanded = parseInt(req.params.expanded);
|
||||
|
||||
@ -150,7 +149,7 @@ function setExpanded(req: Request) {
|
||||
}
|
||||
}
|
||||
|
||||
function setExpandedForSubtree(req: Request) {
|
||||
function setExpandedForSubtree(req: Request<{ branchId: string, expanded: string }>) {
|
||||
const { branchId } = req.params;
|
||||
const expanded = parseInt(req.params.expanded);
|
||||
|
||||
@ -232,7 +231,7 @@ function setExpandedForSubtree(req: Request) {
|
||||
* - session: []
|
||||
* tags: ["data"]
|
||||
*/
|
||||
function deleteBranch(req: Request) {
|
||||
function deleteBranch(req: Request<{ branchId: string }>) {
|
||||
const last = req.query.last === "true";
|
||||
const eraseNotes = req.query.eraseNotes === "true";
|
||||
const branch = becca.getBranchOrThrow(req.params.branchId);
|
||||
@ -256,11 +255,11 @@ function deleteBranch(req: Request) {
|
||||
}
|
||||
|
||||
return {
|
||||
noteDeleted: noteDeleted
|
||||
noteDeleted
|
||||
};
|
||||
}
|
||||
|
||||
function setPrefix(req: Request) {
|
||||
function setPrefix(req: Request<{ branchId: string }>) {
|
||||
const branchId = req.params.branchId;
|
||||
//TriliumNextTODO: req.body arrives as string, so req.body.prefix will be undefined – did the code below ever even work?
|
||||
const prefix = utils.isEmptyOrWhitespace(req.body.prefix) ? null : req.body.prefix;
|
||||
@ -272,7 +271,7 @@ function setPrefix(req: Request) {
|
||||
|
||||
function setPrefixBatch(req: Request) {
|
||||
const { branchIds, prefix } = req.body;
|
||||
|
||||
|
||||
if (!Array.isArray(branchIds)) {
|
||||
throw new ValidationError("branchIds must be an array");
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ async function addClipping(req: Request) {
|
||||
if (!clippingNote) {
|
||||
clippingNote = noteService.createNewNote({
|
||||
parentNoteId: clipperInbox.noteId,
|
||||
title: title,
|
||||
title,
|
||||
content: "",
|
||||
type: "text"
|
||||
}).note;
|
||||
@ -188,7 +188,7 @@ export function processContent(images: Image[], note: BNote, content: string) {
|
||||
return rewrittenContent;
|
||||
}
|
||||
|
||||
function openNote(req: Request) {
|
||||
function openNote(req: Request<{ noteId: string }>) {
|
||||
if (utils.isElectron) {
|
||||
ws.sendMessageToAllClients({
|
||||
type: "openNote",
|
||||
@ -198,11 +198,11 @@ function openNote(req: Request) {
|
||||
return {
|
||||
result: "ok"
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
result: "open-in-browser"
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
result: "open-in-browser"
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
function handshake() {
|
||||
@ -212,7 +212,7 @@ function handshake() {
|
||||
};
|
||||
}
|
||||
|
||||
async function findNotesByUrl(req: Request) {
|
||||
async function findNotesByUrl(req: Request<{ noteUrl: string }>) {
|
||||
const pageUrl = req.params.noteUrl;
|
||||
const clipperInbox = await getClipperInboxNote();
|
||||
const foundPage = findClippingNote(clipperInbox, pageUrl, null);
|
||||
|
||||
@ -1,29 +1,28 @@
|
||||
"use strict";
|
||||
|
||||
import type { Request } from "express";
|
||||
|
||||
import cloningService from "../../services/cloning.js";
|
||||
|
||||
function cloneNoteToBranch(req: Request) {
|
||||
function cloneNoteToBranch(req: Request<{ noteId: string; parentBranchId: string }>) {
|
||||
const { noteId, parentBranchId } = req.params;
|
||||
const { prefix } = req.body;
|
||||
|
||||
return cloningService.cloneNoteToBranch(noteId, parentBranchId, prefix);
|
||||
}
|
||||
|
||||
function cloneNoteToParentNote(req: Request) {
|
||||
function cloneNoteToParentNote(req: Request<{ noteId: string; parentNoteId: string }>) {
|
||||
const { noteId, parentNoteId } = req.params;
|
||||
const { prefix } = req.body;
|
||||
|
||||
return cloningService.cloneNoteToParentNote(noteId, parentNoteId, prefix);
|
||||
}
|
||||
|
||||
function cloneNoteAfter(req: Request) {
|
||||
function cloneNoteAfter(req: Request<{ noteId: string; afterBranchId: string }>) {
|
||||
const { noteId, afterBranchId } = req.params;
|
||||
|
||||
return cloningService.cloneNoteAfter(noteId, afterBranchId);
|
||||
}
|
||||
|
||||
function toggleNoteInParent(req: Request) {
|
||||
function toggleNoteInParent(req: Request<{ noteId: string; parentNoteId: string; present: string }>) {
|
||||
const { noteId, parentNoteId, present } = req.params;
|
||||
|
||||
return cloningService.toggleNoteInParent(present === "true", noteId, parentNoteId);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import type { Request } from "express";
|
||||
import etapiTokenService from "../../services/etapi_tokens.js";
|
||||
import { EtapiToken, PostTokensResponse } from "@triliumnext/commons";
|
||||
import type { Request } from "express";
|
||||
|
||||
import etapiTokenService from "../../services/etapi_tokens.js";
|
||||
|
||||
function getTokens() {
|
||||
const tokens = etapiTokenService.getTokens();
|
||||
@ -14,11 +15,11 @@ function createToken(req: Request) {
|
||||
return etapiTokenService.createToken(req.body.tokenName) satisfies PostTokensResponse;
|
||||
}
|
||||
|
||||
function patchToken(req: Request) {
|
||||
function patchToken(req: Request<{ etapiTokenId: string }>) {
|
||||
etapiTokenService.renameToken(req.params.etapiTokenId, req.body.name);
|
||||
}
|
||||
|
||||
function deleteToken(req: Request) {
|
||||
function deleteToken(req: Request<{ etapiTokenId: string }>) {
|
||||
etapiTokenService.deleteToken(req.params.etapiTokenId);
|
||||
}
|
||||
|
||||
|
||||
@ -1,17 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
import zipExportService from "../../services/export/zip.js";
|
||||
import singleExportService from "../../services/export/single.js";
|
||||
import opmlExportService from "../../services/export/opml.js";
|
||||
import becca from "../../becca/becca.js";
|
||||
import TaskContext from "../../services/task_context.js";
|
||||
import log from "../../services/log.js";
|
||||
import NotFoundError from "../../errors/not_found_error.js";
|
||||
import type { Request, Response } from "express";
|
||||
|
||||
import becca from "../../becca/becca.js";
|
||||
import NotFoundError from "../../errors/not_found_error.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import opmlExportService from "../../services/export/opml.js";
|
||||
import singleExportService from "../../services/export/single.js";
|
||||
import zipExportService from "../../services/export/zip.js";
|
||||
import log from "../../services/log.js";
|
||||
import TaskContext from "../../services/task_context.js";
|
||||
import { safeExtractMessageAndStackFromError } from "../../services/utils.js";
|
||||
|
||||
function exportBranch(req: Request, res: Response) {
|
||||
function exportBranch(req: Request<{ branchId: string; type: string; format: string; version: string; taskId: string }>, res: Response) {
|
||||
const { branchId, type, format, version, taskId } = req.params;
|
||||
const branch = becca.getBranch(branchId);
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
import chokidar from "chokidar";
|
||||
import type { Request, Response } from "express";
|
||||
import fs from "fs";
|
||||
@ -17,7 +15,7 @@ import protectedSessionService from "../../services/protected_session.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import ws from "../../services/ws.js";
|
||||
|
||||
function updateFile(req: Request) {
|
||||
function updateFile(req: Request<{ noteId: string }>) {
|
||||
const note = becca.getNoteOrThrow(req.params.noteId);
|
||||
|
||||
const file = req.file;
|
||||
@ -46,7 +44,7 @@ function updateFile(req: Request) {
|
||||
};
|
||||
}
|
||||
|
||||
function updateAttachment(req: Request) {
|
||||
function updateAttachment(req: Request<{ attachmentId: string }>) {
|
||||
const attachment = becca.getAttachmentOrThrow(req.params.attachmentId);
|
||||
const file = req.file;
|
||||
if (!file) {
|
||||
@ -103,20 +101,20 @@ function downloadAttachmentInt(attachmentId: string, res: Response, contentDispo
|
||||
return downloadData(attachment, res, contentDisposition);
|
||||
}
|
||||
|
||||
const downloadFile = (req: Request, res: Response) => downloadNoteInt(req.params.noteId, res, true);
|
||||
const openFile = (req: Request, res: Response) => downloadNoteInt(req.params.noteId, res, false);
|
||||
const downloadFile = (req: Request<{ noteId: string }>, res: Response) => downloadNoteInt(req.params.noteId, res, true);
|
||||
const openFile = (req: Request<{ noteId: string }>, res: Response) => downloadNoteInt(req.params.noteId, res, false);
|
||||
|
||||
const downloadAttachment = (req: Request, res: Response) => downloadAttachmentInt(req.params.attachmentId, res, true);
|
||||
const openAttachment = (req: Request, res: Response) => downloadAttachmentInt(req.params.attachmentId, res, false);
|
||||
const downloadAttachment = (req: Request<{ attachmentId: string }>, res: Response) => downloadAttachmentInt(req.params.attachmentId, res, true);
|
||||
const openAttachment = (req: Request<{ attachmentId: string }>, res: Response) => downloadAttachmentInt(req.params.attachmentId, res, false);
|
||||
|
||||
function fileContentProvider(req: Request) {
|
||||
function fileContentProvider(req: Request<{ noteId: string }>) {
|
||||
// Read the file name from route params.
|
||||
const note = becca.getNoteOrThrow(req.params.noteId);
|
||||
|
||||
return streamContent(note.getContent(), note.getFileName(), note.mime);
|
||||
}
|
||||
|
||||
function attachmentContentProvider(req: Request) {
|
||||
function attachmentContentProvider(req: Request<{ attachmentId: string }>) {
|
||||
// Read the file name from route params.
|
||||
const attachment = becca.getAttachmentOrThrow(req.params.attachmentId);
|
||||
|
||||
@ -149,7 +147,7 @@ async function streamContent(content: string | Buffer, fileName: string, mimeTyp
|
||||
};
|
||||
}
|
||||
|
||||
function saveNoteToTmpDir(req: Request) {
|
||||
function saveNoteToTmpDir(req: Request<{ noteId: string }>) {
|
||||
const note = becca.getNoteOrThrow(req.params.noteId);
|
||||
const fileName = note.getFileName();
|
||||
const content = note.getContent();
|
||||
@ -157,7 +155,7 @@ function saveNoteToTmpDir(req: Request) {
|
||||
return saveToTmpDir(fileName, content, "notes", note.noteId);
|
||||
}
|
||||
|
||||
function saveAttachmentToTmpDir(req: Request) {
|
||||
function saveAttachmentToTmpDir(req: Request<{ attachmentId: string }>) {
|
||||
const attachment = becca.getAttachmentOrThrow(req.params.attachmentId);
|
||||
const fileName = attachment.getFileName();
|
||||
const content = attachment.getContent();
|
||||
@ -205,7 +203,7 @@ function saveToTmpDir(fileName: string, content: string | Buffer, entityType: st
|
||||
};
|
||||
}
|
||||
|
||||
function uploadModifiedFileToNote(req: Request) {
|
||||
function uploadModifiedFileToNote(req: Request<{ noteId: string }>) {
|
||||
const noteId = req.params.noteId;
|
||||
const { filePath } = req.body;
|
||||
|
||||
@ -228,7 +226,7 @@ function uploadModifiedFileToNote(req: Request) {
|
||||
note.setContent(fileContent);
|
||||
}
|
||||
|
||||
function uploadModifiedFileToAttachment(req: Request) {
|
||||
function uploadModifiedFileToAttachment(req: Request<{ attachmentId: string }>) {
|
||||
const { attachmentId } = req.params;
|
||||
const { filePath } = req.body;
|
||||
|
||||
|
||||
@ -1,20 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
import imageService from "../../services/image.js";
|
||||
import becca from "../../becca/becca.js";
|
||||
import fs from "fs";
|
||||
import type { Request, Response } from "express";
|
||||
import fs from "fs";
|
||||
|
||||
import becca from "../../becca/becca.js";
|
||||
import type BNote from "../../becca/entities/bnote.js";
|
||||
import type BRevision from "../../becca/entities/brevision.js";
|
||||
import imageService from "../../services/image.js";
|
||||
import { RESOURCE_DIR } from "../../services/resource_dir.js";
|
||||
|
||||
function returnImageFromNote(req: Request, res: Response) {
|
||||
function returnImageFromNote(req: Request<{ noteId: string }>, res: Response) {
|
||||
const image = becca.getNote(req.params.noteId);
|
||||
|
||||
return returnImageInt(image, res);
|
||||
}
|
||||
|
||||
function returnImageFromRevision(req: Request, res: Response) {
|
||||
function returnImageFromRevision(req: Request<{ revisionId: string }>, res: Response) {
|
||||
const image = becca.getRevision(req.params.revisionId);
|
||||
|
||||
return returnImageInt(image, res);
|
||||
@ -61,7 +60,7 @@ export function renderSvgAttachment(image: BNote | BRevision, res: Response, att
|
||||
res.send(svg);
|
||||
}
|
||||
|
||||
function returnAttachedImage(req: Request, res: Response) {
|
||||
function returnAttachedImage(req: Request<{ attachmentId: string }>, res: Response) {
|
||||
const attachment = becca.getAttachment(req.params.attachmentId);
|
||||
|
||||
if (!attachment) {
|
||||
@ -78,7 +77,7 @@ function returnAttachedImage(req: Request, res: Response) {
|
||||
res.send(attachment.getContent());
|
||||
}
|
||||
|
||||
function updateImage(req: Request) {
|
||||
function updateImage(req: Request<{ noteId: string }>) {
|
||||
const { noteId } = req.params;
|
||||
const { file } = req;
|
||||
|
||||
|
||||
@ -1,21 +1,20 @@
|
||||
"use strict";
|
||||
|
||||
import enexImportService from "../../services/import/enex.js";
|
||||
import opmlImportService from "../../services/import/opml.js";
|
||||
import zipImportService from "../../services/import/zip.js";
|
||||
import singleImportService from "../../services/import/single.js";
|
||||
import cls from "../../services/cls.js";
|
||||
import type { Request } from "express";
|
||||
import path from "path";
|
||||
|
||||
import becca from "../../becca/becca.js";
|
||||
import beccaLoader from "../../becca/becca_loader.js";
|
||||
import type BNote from "../../becca/entities/bnote.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import cls from "../../services/cls.js";
|
||||
import enexImportService from "../../services/import/enex.js";
|
||||
import opmlImportService from "../../services/import/opml.js";
|
||||
import singleImportService from "../../services/import/single.js";
|
||||
import zipImportService from "../../services/import/zip.js";
|
||||
import log from "../../services/log.js";
|
||||
import TaskContext from "../../services/task_context.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import type { Request } from "express";
|
||||
import type BNote from "../../becca/entities/bnote.js";
|
||||
import { safeExtractMessageAndStackFromError } from "../../services/utils.js";
|
||||
|
||||
async function importNotesToBranch(req: Request) {
|
||||
async function importNotesToBranch(req: Request<{ parentNoteId: string }>) {
|
||||
const { parentNoteId } = req.params;
|
||||
const { taskId, last } = req.body;
|
||||
|
||||
@ -88,7 +87,7 @@ async function importNotesToBranch(req: Request) {
|
||||
setTimeout(
|
||||
() =>
|
||||
taskContext.taskSucceeded({
|
||||
parentNoteId: parentNoteId,
|
||||
parentNoteId,
|
||||
importedNoteId: note?.noteId
|
||||
}),
|
||||
1000
|
||||
@ -101,7 +100,7 @@ async function importNotesToBranch(req: Request) {
|
||||
return note.getPojo();
|
||||
}
|
||||
|
||||
function importAttachmentsToNote(req: Request) {
|
||||
function importAttachmentsToNote(req: Request<{ parentNoteId: string }>) {
|
||||
const { parentNoteId } = req.params;
|
||||
const { taskId, last } = req.body;
|
||||
|
||||
@ -138,7 +137,7 @@ function importAttachmentsToNote(req: Request) {
|
||||
setTimeout(
|
||||
() =>
|
||||
taskContext.taskSucceeded({
|
||||
parentNoteId: parentNoteId
|
||||
parentNoteId
|
||||
}),
|
||||
1000
|
||||
);
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
import becca from "../../becca/becca.js";
|
||||
import type BNote from "../../becca/entities/bnote.js";
|
||||
import type BAttribute from "../../becca/entities/battribute.js";
|
||||
|
||||
import { BacklinkCountResponse, BacklinksResponse } from "@triliumnext/commons";
|
||||
import type { Request } from "express";
|
||||
import { HTMLElement, parse, TextNode } from "node-html-parser";
|
||||
import { BacklinkCountResponse, BacklinksResponse } from "@triliumnext/commons";
|
||||
|
||||
import becca from "../../becca/becca.js";
|
||||
import type BAttribute from "../../becca/entities/battribute.js";
|
||||
import type BNote from "../../becca/entities/bnote.js";
|
||||
|
||||
interface TreeLink {
|
||||
sourceNoteId: string;
|
||||
@ -97,7 +98,7 @@ function getNeighbors(note: BNote, depth: number): string[] {
|
||||
return retNoteIds;
|
||||
}
|
||||
|
||||
function getLinkMap(req: Request) {
|
||||
function getLinkMap(req: Request<{ noteId: string }>) {
|
||||
const mapRootNote = becca.getNoteOrThrow(req.params.noteId);
|
||||
|
||||
// if the map root itself has "excludeFromNoteMap" attribute (journal typically) then there wouldn't be anything
|
||||
@ -156,9 +157,9 @@ function getLinkMap(req: Request) {
|
||||
return false;
|
||||
} else if (excludeRelations.has(rel.name)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
})
|
||||
.map((rel) => ({
|
||||
id: `${rel.noteId}-${rel.name}-${rel.value}`,
|
||||
@ -168,13 +169,13 @@ function getLinkMap(req: Request) {
|
||||
}));
|
||||
|
||||
return {
|
||||
notes: notes,
|
||||
notes,
|
||||
noteIdToDescendantCountMap: buildDescendantCountMap(noteIdsArray),
|
||||
links: links
|
||||
links
|
||||
};
|
||||
}
|
||||
|
||||
function getTreeMap(req: Request) {
|
||||
function getTreeMap(req: Request<{ noteId: string }>) {
|
||||
const mapRootNote = becca.getNoteOrThrow(req.params.noteId);
|
||||
// if the map root itself has "excludeFromNoteMap" (journal typically) then there wouldn't be anything to display,
|
||||
// so we'll just ignore it
|
||||
@ -223,9 +224,9 @@ function getTreeMap(req: Request) {
|
||||
updateDescendantCountMapForSearch(noteIdToDescendantCountMap, subtree.relationships);
|
||||
|
||||
return {
|
||||
notes: notes,
|
||||
noteIdToDescendantCountMap: noteIdToDescendantCountMap,
|
||||
links: links
|
||||
notes,
|
||||
noteIdToDescendantCountMap,
|
||||
links
|
||||
};
|
||||
}
|
||||
|
||||
@ -350,7 +351,7 @@ function getFilteredBacklinks(note: BNote): BAttribute[] {
|
||||
);
|
||||
}
|
||||
|
||||
function getBacklinkCount(req: Request) {
|
||||
function getBacklinkCount(req: Request<{ noteId: string }>) {
|
||||
const { noteId } = req.params;
|
||||
|
||||
const note = becca.getNoteOrThrow(noteId);
|
||||
@ -360,7 +361,7 @@ function getBacklinkCount(req: Request) {
|
||||
} satisfies BacklinkCountResponse;
|
||||
}
|
||||
|
||||
function getBacklinks(req: Request): BacklinksResponse {
|
||||
function getBacklinks(req: Request<{ noteId: string }>): BacklinksResponse {
|
||||
const { noteId } = req.params;
|
||||
const note = becca.getNoteOrThrow(noteId);
|
||||
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
import noteService from "../../services/notes.js";
|
||||
import eraseService from "../../services/erase.js";
|
||||
import treeService from "../../services/tree.js";
|
||||
import sql from "../../services/sql.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import log from "../../services/log.js";
|
||||
import TaskContext from "../../services/task_context.js";
|
||||
|
||||
import type { AttributeRow, CreateChildrenResponse, DeleteNotesPreview, MetadataResponse } from "@triliumnext/commons";
|
||||
import type { Request } from "express";
|
||||
|
||||
import becca from "../../becca/becca.js";
|
||||
import type BBranch from "../../becca/entities/bbranch.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import blobService from "../../services/blob.js";
|
||||
import type { Request } from "express";
|
||||
import type BBranch from "../../becca/entities/bbranch.js";
|
||||
import type { AttributeRow, CreateChildrenResponse, DeleteNotesPreview, MetadataResponse } from "@triliumnext/commons";
|
||||
import eraseService from "../../services/erase.js";
|
||||
import log from "../../services/log.js";
|
||||
import noteService from "../../services/notes.js";
|
||||
import sql from "../../services/sql.js";
|
||||
import TaskContext from "../../services/task_context.js";
|
||||
import treeService from "../../services/tree.js";
|
||||
import utils from "../../services/utils.js";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
@ -39,7 +40,7 @@ import type { AttributeRow, CreateChildrenResponse, DeleteNotesPreview, Metadata
|
||||
* - session: []
|
||||
* tags: ["data"]
|
||||
*/
|
||||
function getNote(req: Request) {
|
||||
function getNote(req: Request<{ noteId: string }>) {
|
||||
return becca.getNoteOrThrow(req.params.noteId);
|
||||
}
|
||||
|
||||
@ -66,7 +67,7 @@ function getNote(req: Request) {
|
||||
* - session: []
|
||||
* tags: ["data"]
|
||||
*/
|
||||
function getNoteBlob(req: Request) {
|
||||
function getNoteBlob(req: Request<{ noteId: string }>) {
|
||||
return blobService.getBlobPojo("notes", req.params.noteId);
|
||||
}
|
||||
|
||||
@ -93,7 +94,7 @@ function getNoteBlob(req: Request) {
|
||||
* - session: []
|
||||
* tags: ["data"]
|
||||
*/
|
||||
function getNoteMetadata(req: Request) {
|
||||
function getNoteMetadata(req: Request<{ noteId: string }>) {
|
||||
const note = becca.getNoteOrThrow(req.params.noteId);
|
||||
|
||||
return {
|
||||
@ -126,7 +127,7 @@ function createNote(req: Request) {
|
||||
} satisfies CreateChildrenResponse;
|
||||
}
|
||||
|
||||
function updateNoteData(req: Request) {
|
||||
function updateNoteData(req: Request<{ noteId: string }>) {
|
||||
const { content, attachments } = req.body;
|
||||
const { noteId } = req.params;
|
||||
|
||||
@ -170,7 +171,7 @@ function updateNoteData(req: Request) {
|
||||
* - session: []
|
||||
* tags: ["data"]
|
||||
*/
|
||||
function deleteNote(req: Request) {
|
||||
function deleteNote(req: Request<{ noteId: string }>) {
|
||||
const noteId = req.params.noteId;
|
||||
const taskId = req.query.taskId;
|
||||
const eraseNotes = req.query.eraseNotes === "true";
|
||||
@ -197,7 +198,7 @@ function deleteNote(req: Request) {
|
||||
}
|
||||
}
|
||||
|
||||
function undeleteNote(req: Request) {
|
||||
function undeleteNote(req: Request<{ noteId: string }>) {
|
||||
const taskContext = TaskContext.getInstance(utils.randomString(10), "undeleteNotes", null);
|
||||
|
||||
noteService.undeleteNote(req.params.noteId, taskContext);
|
||||
@ -205,7 +206,7 @@ function undeleteNote(req: Request) {
|
||||
taskContext.taskSucceeded(null);
|
||||
}
|
||||
|
||||
function sortChildNotes(req: Request) {
|
||||
function sortChildNotes(req: Request<{ noteId: string }>) {
|
||||
const noteId = req.params.noteId;
|
||||
const { sortBy, sortDirection, foldersFirst, sortNatural, sortLocale } = req.body;
|
||||
|
||||
@ -216,7 +217,7 @@ function sortChildNotes(req: Request) {
|
||||
treeService.sortNotes(noteId, sortBy, reverse, foldersFirst, sortNatural, sortLocale);
|
||||
}
|
||||
|
||||
function protectNote(req: Request) {
|
||||
function protectNote(req: Request<{ noteId: string; isProtected: string }>) {
|
||||
const noteId = req.params.noteId;
|
||||
const note = becca.notes[noteId];
|
||||
const protect = !!parseInt(req.params.isProtected);
|
||||
@ -229,7 +230,7 @@ function protectNote(req: Request) {
|
||||
taskContext.taskSucceeded(null);
|
||||
}
|
||||
|
||||
function setNoteTypeMime(req: Request) {
|
||||
function setNoteTypeMime(req: Request<{ noteId: string }>) {
|
||||
// can't use [] destructuring because req.params is not iterable
|
||||
const { noteId } = req.params;
|
||||
const { type, mime } = req.body;
|
||||
@ -240,7 +241,7 @@ function setNoteTypeMime(req: Request) {
|
||||
note.save();
|
||||
}
|
||||
|
||||
function changeTitle(req: Request) {
|
||||
function changeTitle(req: Request<{ noteId: string }>) {
|
||||
const noteId = req.params.noteId;
|
||||
const title = req.body.title;
|
||||
|
||||
@ -267,7 +268,7 @@ function changeTitle(req: Request) {
|
||||
return note;
|
||||
}
|
||||
|
||||
function duplicateSubtree(req: Request) {
|
||||
function duplicateSubtree(req: Request<{ noteId: string; parentNoteId: string }>) {
|
||||
const { noteId, parentNoteId } = req.params;
|
||||
|
||||
return noteService.duplicateSubtree(noteId, parentNoteId);
|
||||
@ -342,7 +343,7 @@ function getDeleteNotesPreview(req: Request) {
|
||||
} satisfies DeleteNotesPreview;
|
||||
}
|
||||
|
||||
function forceSaveRevision(req: Request) {
|
||||
function forceSaveRevision(req: Request<{ noteId: string }>) {
|
||||
const { noteId } = req.params;
|
||||
const note = becca.getNoteOrThrow(noteId);
|
||||
|
||||
@ -353,7 +354,7 @@ function forceSaveRevision(req: Request) {
|
||||
note.saveRevision();
|
||||
}
|
||||
|
||||
function convertNoteToAttachment(req: Request) {
|
||||
function convertNoteToAttachment(req: Request<{ noteId: string }>) {
|
||||
const { noteId } = req.params;
|
||||
const note = becca.getNoteOrThrow(noteId);
|
||||
|
||||
|
||||
@ -128,7 +128,7 @@ function getOptions() {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
function updateOption(req: Request) {
|
||||
function updateOption(req: Request<{ name: string; value: string }>) {
|
||||
const { name, value } = req.params;
|
||||
|
||||
if (!update(name, value)) {
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
import sql from "../../services/sql.js";
|
||||
import protectedSessionService from "../../services/protected_session.js";
|
||||
import noteService from "../../services/notes.js";
|
||||
import becca from "../../becca/becca.js";
|
||||
import type { Request } from "express";
|
||||
import type { RecentChangeRow } from "@triliumnext/commons";
|
||||
import type { Request } from "express";
|
||||
|
||||
function getRecentChanges(req: Request) {
|
||||
import becca from "../../becca/becca.js";
|
||||
import noteService from "../../services/notes.js";
|
||||
import protectedSessionService from "../../services/protected_session.js";
|
||||
import sql from "../../services/sql.js";
|
||||
|
||||
function getRecentChanges(req: Request<{ ancestorNoteId: string }>) {
|
||||
const { ancestorNoteId } = req.params;
|
||||
|
||||
let recentChanges: RecentChangeRow[] = [];
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
import beccaService from "../../becca/becca_service.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import sql from "../../services/sql.js";
|
||||
import cls from "../../services/cls.js";
|
||||
import path from "path";
|
||||
import becca from "../../becca/becca.js";
|
||||
import blobService from "../../services/blob.js";
|
||||
import eraseService from "../../services/erase.js";
|
||||
import type { Request, Response } from "express";
|
||||
import type BRevision from "../../becca/entities/brevision.js";
|
||||
import type BNote from "../../becca/entities/bnote.js";
|
||||
import type { NotePojo } from "../../becca/becca-interface.js";
|
||||
|
||||
import { EditedNotesResponse, RevisionItem, RevisionPojo, RevisionRow } from "@triliumnext/commons";
|
||||
import type { Request, Response } from "express";
|
||||
import path from "path";
|
||||
|
||||
import becca from "../../becca/becca.js";
|
||||
import beccaService from "../../becca/becca_service.js";
|
||||
import type { NotePojo } from "../../becca/becca-interface.js";
|
||||
import type BNote from "../../becca/entities/bnote.js";
|
||||
import type BRevision from "../../becca/entities/brevision.js";
|
||||
import blobService from "../../services/blob.js";
|
||||
import cls from "../../services/cls.js";
|
||||
import eraseService from "../../services/erase.js";
|
||||
import sql from "../../services/sql.js";
|
||||
import utils from "../../services/utils.js";
|
||||
|
||||
interface NotePath {
|
||||
noteId: string;
|
||||
@ -26,13 +27,13 @@ interface NotePojoWithNotePath extends NotePojo {
|
||||
notePath?: string[] | null;
|
||||
}
|
||||
|
||||
function getRevisionBlob(req: Request) {
|
||||
function getRevisionBlob(req: Request<{ revisionId: string }>) {
|
||||
const preview = req.query.preview === "true";
|
||||
|
||||
return blobService.getBlobPojo("revisions", req.params.revisionId, { preview });
|
||||
}
|
||||
|
||||
function getRevisions(req: Request) {
|
||||
function getRevisions(req: Request<{ noteId: string }>) {
|
||||
return becca.getRevisionsFromQuery(
|
||||
`
|
||||
SELECT revisions.*,
|
||||
@ -45,7 +46,7 @@ function getRevisions(req: Request) {
|
||||
) satisfies RevisionItem[];
|
||||
}
|
||||
|
||||
function getRevision(req: Request) {
|
||||
function getRevision(req: Request<{ revisionId: string }>) {
|
||||
const revision = becca.getRevisionOrThrow(req.params.revisionId);
|
||||
|
||||
if (revision.type === "file") {
|
||||
@ -85,7 +86,7 @@ function getRevisionFilename(revision: BRevision) {
|
||||
return filename;
|
||||
}
|
||||
|
||||
function downloadRevision(req: Request, res: Response) {
|
||||
function downloadRevision(req: Request<{ revisionId: string }>, res: Response) {
|
||||
const revision = becca.getRevisionOrThrow(req.params.revisionId);
|
||||
|
||||
if (!revision.isContentAvailable()) {
|
||||
@ -100,13 +101,13 @@ function downloadRevision(req: Request, res: Response) {
|
||||
res.send(revision.getContent());
|
||||
}
|
||||
|
||||
function eraseAllRevisions(req: Request) {
|
||||
function eraseAllRevisions(req: Request<{ noteId: string }>) {
|
||||
const revisionIdsToErase = sql.getColumn<string>("SELECT revisionId FROM revisions WHERE noteId = ?", [req.params.noteId]);
|
||||
|
||||
eraseService.eraseRevisions(revisionIdsToErase);
|
||||
}
|
||||
|
||||
function eraseRevision(req: Request) {
|
||||
function eraseRevision(req: Request<{ revisionId: string }>) {
|
||||
eraseService.eraseRevisions([req.params.revisionId]);
|
||||
}
|
||||
|
||||
@ -117,7 +118,7 @@ function eraseAllExcessRevisions() {
|
||||
});
|
||||
}
|
||||
|
||||
function restoreRevision(req: Request) {
|
||||
function restoreRevision(req: Request<{ revisionId: string }>) {
|
||||
const revision = becca.getRevision(req.params.revisionId);
|
||||
|
||||
if (revision) {
|
||||
@ -166,7 +167,7 @@ function getEditedNotesOnDate(req: Request) {
|
||||
)
|
||||
ORDER BY isDeleted
|
||||
LIMIT 50`,
|
||||
{ date: `${req.params.date}%` }
|
||||
{ date: `${req.params.date}%` }
|
||||
);
|
||||
|
||||
let notes = becca.getNotes(noteIds, true);
|
||||
@ -204,7 +205,7 @@ function getNotePathData(note: BNote): NotePath | undefined {
|
||||
|
||||
return {
|
||||
noteId: note.noteId,
|
||||
branchId: branchId,
|
||||
branchId,
|
||||
title: noteTitle,
|
||||
notePath: retPath,
|
||||
path: retPath.join("/")
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
import scriptService, { type Bundle } from "../../services/script.js";
|
||||
import attributeService from "../../services/attributes.js";
|
||||
import becca from "../../becca/becca.js";
|
||||
import syncService from "../../services/sync.js";
|
||||
import sql from "../../services/sql.js";
|
||||
|
||||
import type { Request } from "express";
|
||||
|
||||
import becca from "../../becca/becca.js";
|
||||
import attributeService from "../../services/attributes.js";
|
||||
import scriptService, { type Bundle } from "../../services/script.js";
|
||||
import sql from "../../services/sql.js";
|
||||
import syncService from "../../services/sync.js";
|
||||
import { safeExtractMessageAndStackFromError } from "../../services/utils.js";
|
||||
|
||||
interface ScriptBody {
|
||||
@ -43,7 +44,7 @@ async function exec(req: Request) {
|
||||
}
|
||||
}
|
||||
|
||||
function run(req: Request) {
|
||||
function run(req: Request<{ noteId: string }>) {
|
||||
const note = becca.getNoteOrThrow(req.params.noteId);
|
||||
|
||||
const result = scriptService.executeNote(note, { originEntity: note });
|
||||
@ -71,23 +72,23 @@ function getStartupBundles(req: Request) {
|
||||
if (!process.env.TRILIUM_SAFE_MODE) {
|
||||
if (req.query.mobile === "true") {
|
||||
return getBundlesWithLabel("run", "mobileStartup");
|
||||
} else {
|
||||
return getBundlesWithLabel("run", "frontendStartup");
|
||||
}
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
return getBundlesWithLabel("run", "frontendStartup");
|
||||
|
||||
}
|
||||
return [];
|
||||
|
||||
}
|
||||
|
||||
function getWidgetBundles() {
|
||||
if (!process.env.TRILIUM_SAFE_MODE) {
|
||||
return getBundlesWithLabel("widget");
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
|
||||
}
|
||||
|
||||
function getRelationBundles(req: Request) {
|
||||
function getRelationBundles(req: Request<{ noteId: string, relationName: string }>) {
|
||||
const noteId = req.params.noteId;
|
||||
const note = becca.getNoteOrThrow(noteId);
|
||||
const relationName = req.params.relationName;
|
||||
@ -116,7 +117,7 @@ function getRelationBundles(req: Request) {
|
||||
return bundles;
|
||||
}
|
||||
|
||||
function getBundle(req: Request) {
|
||||
function getBundle(req: Request<{ noteId: string }>) {
|
||||
const note = becca.getNoteOrThrow(req.params.noteId);
|
||||
const { script, params } = req.body ?? {};
|
||||
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
|
||||
import type { Request } from "express";
|
||||
|
||||
import becca from "../../becca/becca.js";
|
||||
import SearchContext from "../../services/search/search_context.js";
|
||||
import searchService, { EMPTY_RESULT, type SearchNoteResult } from "../../services/search/services/search.js";
|
||||
import beccaService from "../../becca/becca_service.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import attributeFormatter from "../../services/attribute_formatter.js";
|
||||
import bulkActionService from "../../services/bulk_actions.js";
|
||||
import cls from "../../services/cls.js";
|
||||
import attributeFormatter from "../../services/attribute_formatter.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import type SearchResult from "../../services/search/search_result.js";
|
||||
import hoistedNoteService from "../../services/hoisted_note.js";
|
||||
import beccaService from "../../becca/becca_service.js";
|
||||
import SearchContext from "../../services/search/search_context.js";
|
||||
import type SearchResult from "../../services/search/search_result.js";
|
||||
import searchService, { EMPTY_RESULT, type SearchNoteResult } from "../../services/search/services/search.js";
|
||||
|
||||
function searchFromNote(req: Request): SearchNoteResult {
|
||||
function searchFromNote(req: Request<{ noteId: string }>): SearchNoteResult {
|
||||
const note = becca.getNoteOrThrow(req.params.noteId);
|
||||
|
||||
if (!note) {
|
||||
@ -28,7 +28,7 @@ function searchFromNote(req: Request): SearchNoteResult {
|
||||
return searchService.searchFromNote(note);
|
||||
}
|
||||
|
||||
function searchAndExecute(req: Request) {
|
||||
function searchAndExecute(req: Request<{ noteId: string }>) {
|
||||
const note = becca.getNoteOrThrow(req.params.noteId);
|
||||
|
||||
if (!note) {
|
||||
@ -45,7 +45,7 @@ function searchAndExecute(req: Request) {
|
||||
bulkActionService.executeActionsFromNote(note, searchResultNoteIds);
|
||||
}
|
||||
|
||||
function quickSearch(req: Request) {
|
||||
function quickSearch(req: Request<{ searchString: string }>) {
|
||||
const { searchString } = req.params;
|
||||
|
||||
const searchContext = new SearchContext({
|
||||
@ -82,7 +82,7 @@ function quickSearch(req: Request) {
|
||||
highlightedContentSnippet: result.highlightedContentSnippet,
|
||||
attributeSnippet: result.attributeSnippet,
|
||||
highlightedAttributeSnippet: result.highlightedAttributeSnippet,
|
||||
icon: icon
|
||||
icon
|
||||
};
|
||||
});
|
||||
|
||||
@ -90,12 +90,12 @@ function quickSearch(req: Request) {
|
||||
|
||||
return {
|
||||
searchResultNoteIds: resultNoteIds,
|
||||
searchResults: searchResults,
|
||||
searchResults,
|
||||
error: searchContext.getError()
|
||||
};
|
||||
}
|
||||
|
||||
function search(req: Request) {
|
||||
function search(req: Request<{ searchString: string }>) {
|
||||
const { searchString } = req.params;
|
||||
|
||||
const searchContext = new SearchContext({
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
import { SimilarNoteResponse } from "@triliumnext/commons";
|
||||
import type { Request } from "express";
|
||||
|
||||
import similarityService from "../../becca/similarity.js";
|
||||
import becca from "../../becca/becca.js";
|
||||
import { SimilarNoteResponse } from "@triliumnext/commons";
|
||||
import similarityService from "../../becca/similarity.js";
|
||||
|
||||
async function getSimilarNotes(req: Request) {
|
||||
async function getSimilarNotes(req: Request<{ noteId: string }>) {
|
||||
const noteId = req.params.noteId;
|
||||
|
||||
const _note = becca.getNoteOrThrow(noteId);
|
||||
|
||||
@ -6,33 +6,33 @@ import dateNoteService from "../../services/date_notes.js";
|
||||
import specialNotesService, { type LauncherType } from "../../services/special_notes.js";
|
||||
import sql from "../../services/sql.js";
|
||||
|
||||
function getInboxNote(req: Request) {
|
||||
function getInboxNote(req: Request<{ date: string }>) {
|
||||
return specialNotesService.getInboxNote(req.params.date);
|
||||
}
|
||||
|
||||
function getDayNote(req: Request) {
|
||||
function getDayNote(req: Request<{ date: string }>) {
|
||||
const calendarRootId = req.query.calendarRootId;
|
||||
const calendarRoot = typeof calendarRootId === "string" ? becca.getNoteOrThrow(calendarRootId) : null;
|
||||
return dateNoteService.getDayNote(req.params.date, calendarRoot);
|
||||
}
|
||||
|
||||
function getWeekFirstDayNote(req: Request) {
|
||||
function getWeekFirstDayNote(req: Request<{ date: string }>) {
|
||||
return dateNoteService.getWeekFirstDayNote(req.params.date);
|
||||
}
|
||||
|
||||
function getWeekNote(req: Request) {
|
||||
function getWeekNote(req: Request<{ week: string }>) {
|
||||
return dateNoteService.getWeekNote(req.params.week);
|
||||
}
|
||||
|
||||
function getMonthNote(req: Request) {
|
||||
function getMonthNote(req: Request<{ month: string }>) {
|
||||
return dateNoteService.getMonthNote(req.params.month);
|
||||
}
|
||||
|
||||
function getQuarterNote(req: Request) {
|
||||
function getQuarterNote(req: Request<{ quarter: string }>) {
|
||||
return dateNoteService.getQuarterNote(req.params.quarter);
|
||||
}
|
||||
|
||||
function getYearNote(req: Request) {
|
||||
function getYearNote(req: Request<{ year: string }>) {
|
||||
return dateNoteService.getYearNote(req.params.year);
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ function getHoistedNote() {
|
||||
return becca.getNote(cls.getHoistedNoteId());
|
||||
}
|
||||
|
||||
function createLauncher(req: Request) {
|
||||
function createLauncher(req: Request<{ parentNoteId: string, launcherType: string }>) {
|
||||
return specialNotesService.createLauncher({
|
||||
parentNoteId: req.params.parentNoteId,
|
||||
// TODO: Validate the parameter
|
||||
@ -98,7 +98,7 @@ function createLauncher(req: Request) {
|
||||
});
|
||||
}
|
||||
|
||||
function resetLauncher(req: Request) {
|
||||
function resetLauncher(req: Request<{ noteId: string }>) {
|
||||
return specialNotesService.resetLauncher(req.params.noteId);
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
import sql from "../../services/sql.js";
|
||||
import becca from "../../becca/becca.js";
|
||||
import type { Request } from "express";
|
||||
|
||||
import becca from "../../becca/becca.js";
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import sql from "../../services/sql.js";
|
||||
import { safeExtractMessageAndStackFromError } from "../../services/utils.js";
|
||||
|
||||
interface Table {
|
||||
@ -25,7 +24,7 @@ function getSchema() {
|
||||
return tables;
|
||||
}
|
||||
|
||||
function execute(req: Request) {
|
||||
function execute(req: Request<{ noteId: string }>) {
|
||||
const note = becca.getNoteOrThrow(req.params.noteId);
|
||||
|
||||
const content = note.getContent();
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import sql from "../../services/sql.js";
|
||||
import becca from "../../becca/becca.js";
|
||||
import type { Request } from "express";
|
||||
import { NoteSizeResponse, SubtreeSizeResponse } from "@triliumnext/commons";
|
||||
import type { Request } from "express";
|
||||
|
||||
import becca from "../../becca/becca.js";
|
||||
import sql from "../../services/sql.js";
|
||||
|
||||
function getNoteSize(req: Request) {
|
||||
const { noteId } = req.params;
|
||||
@ -26,7 +27,7 @@ function getNoteSize(req: Request) {
|
||||
} satisfies NoteSizeResponse;
|
||||
}
|
||||
|
||||
function getSubtreeSize(req: Request) {
|
||||
function getSubtreeSize(req: Request<{ noteId: string }>) {
|
||||
const note = becca.getNoteOrThrow(req.params.noteId);
|
||||
|
||||
const subTreeNoteIds = note.getSubtreeNoteIds();
|
||||
|
||||
@ -1,21 +1,22 @@
|
||||
"use strict";
|
||||
|
||||
import syncService from "../../services/sync.js";
|
||||
import syncUpdateService from "../../services/sync_update.js";
|
||||
import entityChangesService from "../../services/entity_changes.js";
|
||||
import sql from "../../services/sql.js";
|
||||
import sqlInit from "../../services/sql_init.js";
|
||||
import optionService from "../../services/options.js";
|
||||
import contentHashService from "../../services/content_hash.js";
|
||||
import log from "../../services/log.js";
|
||||
import syncOptions from "../../services/sync_options.js";
|
||||
import utils, { safeExtractMessageAndStackFromError } from "../../services/utils.js";
|
||||
import ws from "../../services/ws.js";
|
||||
|
||||
import { type EntityChange,SyncTestResponse } from "@triliumnext/commons";
|
||||
import type { Request } from "express";
|
||||
import { t } from "i18next";
|
||||
|
||||
import ValidationError from "../../errors/validation_error.js";
|
||||
import consistencyChecksService from "../../services/consistency_checks.js";
|
||||
import { t } from "i18next";
|
||||
import { SyncTestResponse, type EntityChange } from "@triliumnext/commons";
|
||||
import contentHashService from "../../services/content_hash.js";
|
||||
import entityChangesService from "../../services/entity_changes.js";
|
||||
import log from "../../services/log.js";
|
||||
import optionService from "../../services/options.js";
|
||||
import sql from "../../services/sql.js";
|
||||
import sqlInit from "../../services/sql_init.js";
|
||||
import syncService from "../../services/sync.js";
|
||||
import syncOptions from "../../services/sync_options.js";
|
||||
import syncUpdateService from "../../services/sync_update.js";
|
||||
import utils, { safeExtractMessageAndStackFromError } from "../../services/utils.js";
|
||||
import ws from "../../services/ws.js";
|
||||
|
||||
async function testSync(): Promise<SyncTestResponse> {
|
||||
try {
|
||||
@ -287,10 +288,10 @@ function update(req: Request) {
|
||||
|
||||
if (pageIndex !== pageCount - 1) {
|
||||
return;
|
||||
} else {
|
||||
body = JSON.parse(partialRequests[requestId].payload);
|
||||
delete partialRequests[requestId];
|
||||
}
|
||||
}
|
||||
body = JSON.parse(partialRequests[requestId].payload);
|
||||
delete partialRequests[requestId];
|
||||
|
||||
}
|
||||
|
||||
const { entities, instanceId } = body;
|
||||
@ -314,7 +315,7 @@ function syncFinished() {
|
||||
sqlInit.setDbAsInitialized();
|
||||
}
|
||||
|
||||
function queueSector(req: Request) {
|
||||
function queueSector(req: Request<{ entityName: string; sector: string }>) {
|
||||
const entityName = utils.sanitizeSqlIdentifier(req.params.entityName);
|
||||
const sector = utils.sanitizeSqlIdentifier(req.params.sector);
|
||||
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
import express, { type RequestHandler } from "express";
|
||||
import type { ParamsDictionary } from "express-serve-static-core";
|
||||
import multer from "multer";
|
||||
import log from "../services/log.js";
|
||||
import cls from "../services/cls.js";
|
||||
import sql from "../services/sql.js";
|
||||
import entityChangesService from "../services/entity_changes.js";
|
||||
|
||||
import AbstractBeccaEntity from "../becca/entities/abstract_becca_entity.js";
|
||||
import NotFoundError from "../errors/not_found_error.js";
|
||||
import ValidationError from "../errors/validation_error.js";
|
||||
import auth from "../services/auth.js";
|
||||
import { doubleCsrfProtection as csrfMiddleware } from "./csrf_protection.js";
|
||||
import cls from "../services/cls.js";
|
||||
import entityChangesService from "../services/entity_changes.js";
|
||||
import log from "../services/log.js";
|
||||
import sql from "../services/sql.js";
|
||||
import { safeExtractMessageAndStackFromError } from "../services/utils.js";
|
||||
import { doubleCsrfProtection as csrfMiddleware } from "./csrf_protection.js";
|
||||
|
||||
const MAX_ALLOWED_FILE_SIZE_MB = 250;
|
||||
export const router = express.Router();
|
||||
@ -20,8 +22,8 @@ type HttpMethod = "all" | "get" | "post" | "put" | "delete" | "patch" | "options
|
||||
export type ApiResultHandler = (req: express.Request, res: express.Response, result: unknown) => number;
|
||||
|
||||
type NotAPromise<T> = T & { then?: void };
|
||||
export type ApiRequestHandler = (req: express.Request, res: express.Response, next: express.NextFunction) => unknown;
|
||||
export type SyncRouteRequestHandler = (req: express.Request, res: express.Response, next: express.NextFunction) => NotAPromise<object> | number | string | void | null;
|
||||
export type ApiRequestHandler<P extends ParamsDictionary> = (req: express.Request<P>, res: express.Response, next: express.NextFunction) => unknown;
|
||||
export type SyncRouteRequestHandler<P extends ParamsDictionary> = (req: express.Request<P>, res: express.Response, next: express.NextFunction) => NotAPromise<object> | number | string | void | null;
|
||||
|
||||
/** Handling common patterns. If entity is not caught, serialization to JSON will fail */
|
||||
function convertEntitiesToPojo(result: unknown) {
|
||||
@ -67,9 +69,9 @@ export function apiResultHandler(req: express.Request, res: express.Response, re
|
||||
return send(res, statusCode, response);
|
||||
} else if (result === undefined) {
|
||||
return send(res, 204, "");
|
||||
} else {
|
||||
return send(res, 200, result);
|
||||
}
|
||||
return send(res, 200, result);
|
||||
|
||||
}
|
||||
|
||||
function send(res: express.Response, statusCode: number, response: unknown) {
|
||||
@ -81,34 +83,34 @@ function send(res: express.Response, statusCode: number, response: unknown) {
|
||||
res.status(statusCode).send(response);
|
||||
|
||||
return response.length;
|
||||
} else {
|
||||
const json = JSON.stringify(response);
|
||||
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.status(statusCode).send(json);
|
||||
|
||||
return json.length;
|
||||
}
|
||||
const json = JSON.stringify(response);
|
||||
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.status(statusCode).send(json);
|
||||
|
||||
return json.length;
|
||||
|
||||
}
|
||||
|
||||
export function apiRoute(method: HttpMethod, path: string, routeHandler: SyncRouteRequestHandler) {
|
||||
export function apiRoute<P extends ParamsDictionary>(method: HttpMethod, path: string, routeHandler: SyncRouteRequestHandler<P>) {
|
||||
route(method, path, [auth.checkApiAuth, csrfMiddleware], routeHandler, apiResultHandler);
|
||||
}
|
||||
|
||||
export function asyncApiRoute(method: HttpMethod, path: string, routeHandler: ApiRequestHandler) {
|
||||
export function asyncApiRoute<P extends ParamsDictionary>(method: HttpMethod, path: string, routeHandler: ApiRequestHandler<P>) {
|
||||
asyncRoute(method, path, [auth.checkApiAuth, csrfMiddleware], routeHandler, apiResultHandler);
|
||||
}
|
||||
|
||||
export function route(method: HttpMethod, path: string, middleware: express.Handler[], routeHandler: SyncRouteRequestHandler, resultHandler: ApiResultHandler | null = null) {
|
||||
export function route<P extends ParamsDictionary>(method: HttpMethod, path: string, middleware: express.Handler[], routeHandler: SyncRouteRequestHandler<P>, resultHandler: ApiResultHandler | null = null) {
|
||||
internalRoute(method, path, middleware, routeHandler, resultHandler, true);
|
||||
}
|
||||
|
||||
export function asyncRoute(method: HttpMethod, path: string, middleware: express.Handler[], routeHandler: ApiRequestHandler, resultHandler: ApiResultHandler | null = null) {
|
||||
export function asyncRoute<P extends ParamsDictionary>(method: HttpMethod, path: string, middleware: express.Handler[], routeHandler: ApiRequestHandler<P>, resultHandler: ApiResultHandler | null = null) {
|
||||
internalRoute(method, path, middleware, routeHandler, resultHandler, false);
|
||||
}
|
||||
|
||||
function internalRoute(method: HttpMethod, path: string, middleware: express.Handler[], routeHandler: ApiRequestHandler, resultHandler: ApiResultHandler | null = null, transactional: boolean) {
|
||||
router[method](path, ...(middleware as express.Handler[]), (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
function internalRoute<P extends ParamsDictionary>(method: HttpMethod, path: string, middleware: express.Handler[], routeHandler: ApiRequestHandler<P>, resultHandler: ApiResultHandler | null = null, transactional: boolean) {
|
||||
router[method](path, ...(middleware as express.Handler[]), (req: express.Request<P>, res: express.Response, next: express.NextFunction) => {
|
||||
const start = Date.now();
|
||||
|
||||
try {
|
||||
@ -193,7 +195,7 @@ export function createUploadMiddleware(): RequestHandler {
|
||||
const uploadMiddleware = createUploadMiddleware();
|
||||
|
||||
export const uploadMiddlewareWithErrorHandling = function (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||
uploadMiddleware(req, res, function (err) {
|
||||
uploadMiddleware(req, res, (err) => {
|
||||
if (err?.code === "LIMIT_FILE_SIZE") {
|
||||
res.setHeader("Content-Type", "text/plain").status(400).send(`Cannot upload file because it excceeded max allowed file size of ${MAX_ALLOWED_FILE_SIZE_MB} MiB`);
|
||||
} else {
|
||||
|
||||
@ -10,14 +10,13 @@ import etapiBackupRoute from "../etapi/backup.js";
|
||||
import etapiBranchRoutes from "../etapi/branches.js";
|
||||
import etapiMetricsRoute from "../etapi/metrics.js";
|
||||
import etapiNoteRoutes from "../etapi/notes.js";
|
||||
import etapiRevisionsRoutes from "../etapi/revisions.js";
|
||||
import etapiSpecRoute from "../etapi/spec.js";
|
||||
import etapiSpecialNoteRoutes from "../etapi/special_notes.js";
|
||||
import etapiRevisionsRoutes from "../etapi/revisions.js";
|
||||
import auth from "../services/auth.js";
|
||||
import openID from '../services/open_id.js';
|
||||
import { isElectron } from "../services/utils.js";
|
||||
import shareRoutes from "../share/routes.js";
|
||||
|
||||
import appInfoRoute from "./api/app_info.js";
|
||||
import attachmentsApiRoute from "./api/attachments.js";
|
||||
import attributesRoute from "./api/attributes.js";
|
||||
@ -35,12 +34,10 @@ import fontsRoute from "./api/fonts.js";
|
||||
import imageRoute from "./api/image.js";
|
||||
import importRoute from "./api/import.js";
|
||||
import keysRoute from "./api/keys.js";
|
||||
|
||||
import loginApiRoute from "./api/login.js";
|
||||
import metricsRoute from "./api/metrics.js";
|
||||
import noteMapRoute from "./api/note_map.js";
|
||||
import notesApiRoute from "./api/notes.js";
|
||||
|
||||
import optionsApiRoute from "./api/options.js";
|
||||
import otherRoute from "./api/other.js";
|
||||
import passwordApiRoute from "./api/password.js";
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import type { Request } from "express";
|
||||
import type { Content } from "./Content.js";
|
||||
import type { ParamsDictionary } from "express-serve-static-core";
|
||||
|
||||
/**
|
||||
* @type {function (Request): Promise<Content>}
|
||||
*/
|
||||
export type ContentProvider = (req: Request) => Promise<Content>;
|
||||
export type ContentProvider<P extends ParamsDictionary> = (req: Request<P>) => Promise<Content>;
|
||||
|
||||
@ -3,6 +3,7 @@ import { parseRangeHeader } from "./parseRangeHeader.js";
|
||||
import { RangeParserError } from "./RangeParserError.js";
|
||||
import type { Logger } from "./Logger.js";
|
||||
import type { ContentProvider } from "./ContentProvider.js";
|
||||
import type { ParamsDictionary } from "express-serve-static-core";
|
||||
import { ContentDoesNotExistError } from "./ContentDoesNotExistError.js";
|
||||
import {
|
||||
getRangeHeader,
|
||||
@ -13,8 +14,8 @@ import {
|
||||
setContentLengthHeader,
|
||||
setCacheControlHeaderNoCache
|
||||
} from "./utils.js";
|
||||
export function createPartialContentHandler(contentProvider: ContentProvider, logger: Logger) {
|
||||
return async function handler(req: Request, res: Response) {
|
||||
export function createPartialContentHandler<P extends ParamsDictionary>(contentProvider: ContentProvider<P>, logger: Logger) {
|
||||
return async function handler(req: Request<P>, res: Response) {
|
||||
let content;
|
||||
try {
|
||||
content = await contentProvider(req);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user