chore: 添加远程桌面控制组件、文档和构建产物
This commit is contained in:
234
dist-api/chunk-M2SZ5AIA.js
Normal file
234
dist-api/chunk-M2SZ5AIA.js
Normal file
@@ -0,0 +1,234 @@
|
||||
import {
|
||||
AlreadyExistsError,
|
||||
BadRequestError,
|
||||
NotFoundError,
|
||||
ValidationError,
|
||||
resolveNotebookPath
|
||||
} from "./chunk-ER4KPD22.js";
|
||||
import {
|
||||
asyncHandler,
|
||||
createApiModule,
|
||||
defineApiModule,
|
||||
defineEndpoints,
|
||||
successResponse
|
||||
} from "./chunk-74TMTGBG.js";
|
||||
|
||||
// shared/modules/recycle-bin/api.ts
|
||||
var RECYCLE_BIN_ENDPOINTS = defineEndpoints({
|
||||
list: { path: "/", method: "GET" },
|
||||
restore: { path: "/restore", method: "POST" },
|
||||
permanent: { path: "/permanent", method: "DELETE" },
|
||||
empty: { path: "/empty", method: "DELETE" }
|
||||
});
|
||||
|
||||
// shared/modules/recycle-bin/index.ts
|
||||
var RECYCLE_BIN_MODULE = defineApiModule({
|
||||
id: "recycle-bin",
|
||||
name: "\u56DE\u6536\u7AD9",
|
||||
basePath: "/recycle-bin",
|
||||
order: 40,
|
||||
version: "1.0.0",
|
||||
endpoints: RECYCLE_BIN_ENDPOINTS
|
||||
});
|
||||
|
||||
// api/modules/recycle-bin/routes.ts
|
||||
import express from "express";
|
||||
import fs2 from "fs/promises";
|
||||
import path2 from "path";
|
||||
|
||||
// api/modules/recycle-bin/recycleBinService.ts
|
||||
import fs from "fs/promises";
|
||||
import path from "path";
|
||||
async function restoreFile(srcPath, destPath, deletedDate, year, month, day) {
|
||||
const { fullPath: imagesDir } = resolveNotebookPath(`images/${year}/${month}/${day}`);
|
||||
let content = await fs.readFile(srcPath, "utf-8");
|
||||
const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
||||
let match;
|
||||
const imageReplacements = [];
|
||||
while ((match = imageRegex.exec(content)) !== null) {
|
||||
const imagePath = match[2];
|
||||
const imageName = path.basename(imagePath);
|
||||
const rbImageName = `${deletedDate}_${imageName}`;
|
||||
const { fullPath: srcImagePath } = resolveNotebookPath(`RB/${rbImageName}`);
|
||||
try {
|
||||
await fs.access(srcImagePath);
|
||||
await fs.mkdir(imagesDir, { recursive: true });
|
||||
const destImagePath = path.join(imagesDir, imageName);
|
||||
await fs.rename(srcImagePath, destImagePath);
|
||||
const newImagePath = `images/${year}/${month}/${day}/${imageName}`;
|
||||
imageReplacements.push({ oldPath: imagePath, newPath: newImagePath });
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
for (const { oldPath, newPath } of imageReplacements) {
|
||||
content = content.replace(new RegExp(oldPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), newPath);
|
||||
}
|
||||
await fs.writeFile(destPath, content, "utf-8");
|
||||
await fs.unlink(srcPath);
|
||||
}
|
||||
async function restoreFolder(srcPath, destPath, deletedDate, year, month, day) {
|
||||
await fs.mkdir(destPath, { recursive: true });
|
||||
const entries = await fs.readdir(srcPath, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
const srcEntryPath = path.join(srcPath, entry.name);
|
||||
const destEntryPath = path.join(destPath, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
await restoreFolder(srcEntryPath, destEntryPath, deletedDate, year, month, day);
|
||||
} else if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) {
|
||||
await restoreFile(srcEntryPath, destEntryPath, deletedDate, year, month, day);
|
||||
} else {
|
||||
await fs.rename(srcEntryPath, destEntryPath);
|
||||
}
|
||||
}
|
||||
const remaining = await fs.readdir(srcPath);
|
||||
if (remaining.length === 0) {
|
||||
await fs.rmdir(srcPath);
|
||||
}
|
||||
}
|
||||
|
||||
// api/modules/recycle-bin/routes.ts
|
||||
var router = express.Router();
|
||||
router.get(
|
||||
"/",
|
||||
asyncHandler(async (req, res) => {
|
||||
const { fullPath: rbDir } = resolveNotebookPath("RB");
|
||||
try {
|
||||
await fs2.access(rbDir);
|
||||
} catch {
|
||||
successResponse(res, { groups: [] });
|
||||
return;
|
||||
}
|
||||
const entries = await fs2.readdir(rbDir, { withFileTypes: true });
|
||||
const items = [];
|
||||
for (const entry of entries) {
|
||||
const match = entry.name.match(/^(\d{8})_(.+)$/);
|
||||
if (!match) continue;
|
||||
const [, dateStr, originalName] = match;
|
||||
if (entry.isDirectory()) {
|
||||
items.push({
|
||||
name: entry.name,
|
||||
originalName,
|
||||
type: "dir",
|
||||
deletedDate: dateStr,
|
||||
path: `RB/${entry.name}`
|
||||
});
|
||||
} else if (entry.isFile() && entry.name.toLowerCase().endsWith(".md")) {
|
||||
items.push({
|
||||
name: entry.name,
|
||||
originalName,
|
||||
type: "file",
|
||||
deletedDate: dateStr,
|
||||
path: `RB/${entry.name}`
|
||||
});
|
||||
}
|
||||
}
|
||||
const groupedMap = /* @__PURE__ */ new Map();
|
||||
for (const item of items) {
|
||||
const existing = groupedMap.get(item.deletedDate) || [];
|
||||
existing.push(item);
|
||||
groupedMap.set(item.deletedDate, existing);
|
||||
}
|
||||
const groups = Array.from(groupedMap.entries()).map(([date, items2]) => ({
|
||||
date,
|
||||
items: items2.sort((a, b) => a.originalName.localeCompare(b.originalName))
|
||||
})).sort((a, b) => b.date.localeCompare(a.date));
|
||||
successResponse(res, { groups });
|
||||
})
|
||||
);
|
||||
router.post(
|
||||
"/restore",
|
||||
asyncHandler(async (req, res) => {
|
||||
const { path: relPath, type } = req.body;
|
||||
if (!relPath || !type) {
|
||||
throw new ValidationError("Path and type are required");
|
||||
}
|
||||
const { fullPath: itemPath } = resolveNotebookPath(relPath);
|
||||
try {
|
||||
await fs2.access(itemPath);
|
||||
} catch {
|
||||
throw new NotFoundError("Item not found in recycle bin");
|
||||
}
|
||||
const match = path2.basename(itemPath).match(/^(\d{8})_(.+)$/);
|
||||
if (!match) {
|
||||
throw new BadRequestError("Invalid recycle bin item name");
|
||||
}
|
||||
const [, dateStr, originalName] = match;
|
||||
const year = dateStr.substring(0, 4);
|
||||
const month = dateStr.substring(4, 6);
|
||||
const day = dateStr.substring(6, 8);
|
||||
const { fullPath: markdownsDir } = resolveNotebookPath("markdowns");
|
||||
await fs2.mkdir(markdownsDir, { recursive: true });
|
||||
const destPath = path2.join(markdownsDir, originalName);
|
||||
const existing = await fs2.stat(destPath).catch(() => null);
|
||||
if (existing) {
|
||||
throw new AlreadyExistsError("A file or folder with this name already exists");
|
||||
}
|
||||
if (type === "dir") {
|
||||
await restoreFolder(itemPath, destPath, dateStr, year, month, day);
|
||||
} else {
|
||||
await restoreFile(itemPath, destPath, dateStr, year, month, day);
|
||||
}
|
||||
successResponse(res, null);
|
||||
})
|
||||
);
|
||||
router.delete(
|
||||
"/permanent",
|
||||
asyncHandler(async (req, res) => {
|
||||
const { path: relPath, type } = req.body;
|
||||
if (!relPath || !type) {
|
||||
throw new ValidationError("Path and type are required");
|
||||
}
|
||||
const { fullPath: itemPath } = resolveNotebookPath(relPath);
|
||||
try {
|
||||
await fs2.access(itemPath);
|
||||
} catch {
|
||||
throw new NotFoundError("Item not found in recycle bin");
|
||||
}
|
||||
if (type === "dir") {
|
||||
await fs2.rm(itemPath, { recursive: true, force: true });
|
||||
} else {
|
||||
await fs2.unlink(itemPath);
|
||||
}
|
||||
successResponse(res, null);
|
||||
})
|
||||
);
|
||||
router.delete(
|
||||
"/empty",
|
||||
asyncHandler(async (req, res) => {
|
||||
const { fullPath: rbDir } = resolveNotebookPath("RB");
|
||||
try {
|
||||
await fs2.access(rbDir);
|
||||
} catch {
|
||||
successResponse(res, null);
|
||||
return;
|
||||
}
|
||||
const entries = await fs2.readdir(rbDir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
const entryPath = path2.join(rbDir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
await fs2.rm(entryPath, { recursive: true, force: true });
|
||||
} else {
|
||||
await fs2.unlink(entryPath);
|
||||
}
|
||||
}
|
||||
successResponse(res, null);
|
||||
})
|
||||
);
|
||||
var routes_default = router;
|
||||
|
||||
// api/modules/recycle-bin/index.ts
|
||||
var createRecycleBinModule = () => {
|
||||
return createApiModule(RECYCLE_BIN_MODULE, {
|
||||
routes: (_container) => {
|
||||
return routes_default;
|
||||
}
|
||||
});
|
||||
};
|
||||
var recycle_bin_default = createRecycleBinModule;
|
||||
|
||||
export {
|
||||
restoreFile,
|
||||
restoreFolder,
|
||||
createRecycleBinModule,
|
||||
recycle_bin_default
|
||||
};
|
||||
Reference in New Issue
Block a user