Merge remote-tracking branch 'origin/main' into feature/export_with_share_theme

This commit is contained in:
Elian Doran
2025-10-24 14:43:13 +03:00
1587 changed files with 197821 additions and 41100 deletions

View File

@@ -43,7 +43,6 @@ interface MetricsData {
*/
function formatPrometheusMetrics(data: MetricsData): string {
const lines: string[] = [];
const timestamp = Math.floor(new Date(data.timestamp).getTime() / 1000);
// Helper function to add a metric
const addMetric = (name: string, value: number | null, help: string, type: string = 'gauge', labels: Record<string, string> = {}) => {
@@ -56,7 +55,7 @@ function formatPrometheusMetrics(data: MetricsData): string {
? `{${Object.entries(labels).map(([k, v]) => `${k}="${v}"`).join(',')}}`
: '';
lines.push(`${name}${labelStr} ${value} ${timestamp}`);
lines.push(`${name}${labelStr} ${value}`);
lines.push('');
};

View File

@@ -93,6 +93,7 @@ function register(router: Router) {
throw new eu.EtapiError(400, "NOTE_IS_PROTECTED", `Note '${req.params.noteId}' is protected and cannot be modified through ETAPI.`);
}
noteService.saveRevisionIfNeeded(note);
eu.validateAndPatch(note, req.body, ALLOWED_PROPERTIES_FOR_PATCH);
note.save();
@@ -108,7 +109,7 @@ function register(router: Router) {
return res.sendStatus(204);
}
note.deleteNote(null, new TaskContext("no-progress-reporting"));
note.deleteNote(null, new TaskContext("no-progress-reporting", "deleteNotes", null));
res.sendStatus(204);
});
@@ -137,6 +138,7 @@ function register(router: Router) {
throw new eu.EtapiError(400, "NOTE_IS_PROTECTED", `Note '${req.params.noteId}' is protected and cannot be modified through ETAPI.`);
}
noteService.saveRevisionIfNeeded(note);
note.setContent(req.body);
noteService.asyncPostProcessContent(note, req.body);
@@ -152,7 +154,7 @@ function register(router: Router) {
throw new eu.EtapiError(400, "UNRECOGNIZED_EXPORT_FORMAT", `Unrecognized export format '${format}', supported values are 'html' (default) or 'markdown'.`);
}
const taskContext = new TaskContext("no-progress-reporting");
const taskContext = new TaskContext("no-progress-reporting", "export", null);
// technically a branch is being exported (includes prefix), but it's such a minor difference yet usability pain
// (e.g. branchIds are not seen in UI), that we export "note export" instead.
@@ -163,7 +165,7 @@ function register(router: Router) {
eu.route(router, "post", "/etapi/notes/:noteId/import", (req, res, next) => {
const note = eu.getAndCheckNote(req.params.noteId);
const taskContext = new TaskContext("no-progress-reporting");
const taskContext = new TaskContext("no-progress-reporting", "importNotes", null);
zipImportService.importZip(taskContext, req.body, note).then((importedNote) => {
res.status(201).json({

View File

@@ -3,12 +3,18 @@ import type { Router } from "express";
import fs from "fs";
import path from "path";
import { RESOURCE_DIR } from "../services/resource_dir";
import rateLimit from "express-rate-limit";
const specPath = path.join(RESOURCE_DIR, "etapi.openapi.yaml");
let spec: string | null = null;
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
});
function register(router: Router) {
router.get("/etapi/etapi.openapi.yaml", (_, res) => {
router.get("/etapi/etapi.openapi.yaml", limiter, (_, res) => {
if (!spec) {
spec = fs.readFileSync(specPath, "utf8");
}