You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
3.5 KiB

11 months ago
11 months ago
11 months ago
  1. const fs = require("fs");
  2. const path = require("path");
  3. const {
  4. purgeVectorCache,
  5. purgeSourceDocument,
  6. normalizePath,
  7. isWithin,
  8. documentsPath,
  9. } = require(".");
  10. const { Document } = require("../../models/documents");
  11. const { Workspace } = require("../../models/workspace");
  12. const { DeptDocument } = require("../../models/deptDocument");
  13. // async function purgeDocument(filename = null) {
  14. // if (!filename || !normalizePath(filename)) return;
  15. //
  16. // await purgeVectorCache(filename);
  17. // await purgeSourceDocument(filename);
  18. // const workspaces = await Workspace.where();
  19. // for (const workspace of workspaces) {
  20. // await Document.removeDocuments(workspace, [filename]);
  21. // }
  22. // return;
  23. // }
  24. async function purgeDocument(filename = null) {
  25. if (!filename || !normalizePath(filename)) return;
  26. // 根据环境转换分隔符
  27. let normalizedFilename = filename;
  28. if (process.env.NODE_ENV === "development") {
  29. // 开发环境:将路径分隔符转换为 Windows 风格(\)
  30. normalizedFilename = filename.replace(/\//g, "\\");
  31. } else {
  32. // 生产环境:将路径分隔符转换为 Unix 风格(/)
  33. normalizedFilename = filename.replace(/\\/g, "/");
  34. }
  35. // 标记匹配的文件为逻辑删除
  36. const { success, error, count } = await DeptDocument.softDeleteByParsedFilePath(normalizedFilename);
  37. if (!success) {
  38. console.error("Failed to soft delete documents:", error);
  39. return;
  40. }
  41. console.log(`Successfully marked ${count} documents as deleted.`);
  42. // 继续执行原有的清理逻辑
  43. await purgeVectorCache(filename);
  44. await purgeSourceDocument(filename);
  45. const workspaces = await Workspace.where();
  46. for (const workspace of workspaces) {
  47. await Document.removeDocuments(workspace, [filename]);
  48. }
  49. return;
  50. }
  51. async function purgeFolder(folderName = null) {
  52. if (!folderName) return;
  53. const subFolder = normalizePath(folderName);
  54. const subFolderPath = path.resolve(documentsPath, subFolder);
  55. const validRemovableSubFolders = fs
  56. .readdirSync(documentsPath)
  57. .map((folder) => {
  58. // Filter out any results which are not folders or
  59. // are the protected custom-documents folder.
  60. if (folder === "custom-documents") return null;
  61. const subfolderPath = path.resolve(documentsPath, folder);
  62. if (!fs.lstatSync(subfolderPath).isDirectory()) return null;
  63. return folder;
  64. })
  65. .filter((subFolder) => !!subFolder);
  66. if (
  67. !validRemovableSubFolders.includes(subFolder) ||
  68. !fs.existsSync(subFolderPath) ||
  69. !isWithin(documentsPath, subFolderPath)
  70. )
  71. return;
  72. const filenames = fs
  73. .readdirSync(subFolderPath)
  74. .map((file) =>
  75. path.join(subFolderPath, file).replace(documentsPath + "/", "")
  76. );
  77. const workspaces = await Workspace.where();
  78. const purgePromises = [];
  79. // Remove associated Vector-cache files
  80. for (const filename of filenames) {
  81. const rmVectorCache = () =>
  82. new Promise((resolve) =>
  83. purgeVectorCache(filename).then(() => resolve(true))
  84. );
  85. purgePromises.push(rmVectorCache);
  86. }
  87. // Remove workspace document associations
  88. for (const workspace of workspaces) {
  89. const rmWorkspaceDoc = () =>
  90. new Promise((resolve) =>
  91. Document.removeDocuments(workspace, filenames).then(() => resolve(true))
  92. );
  93. purgePromises.push(rmWorkspaceDoc);
  94. }
  95. await Promise.all(purgePromises.flat().map((f) => f()));
  96. fs.rmSync(subFolderPath, { recursive: true }); // Delete target document-folder and source files.
  97. return;
  98. }
  99. module.exports = {
  100. purgeDocument,
  101. purgeFolder,
  102. };