@openinc/parse-server-opendash
Version:
Parse Server Cloud Code for open.INC Stack.
168 lines (167 loc) • 7.19 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DocumentationCleanup = void 0;
const types_1 = require("../../../types");
/**
* Service for cleaning up old documentation that no longer exists in the repository
*/
class DocumentationCleanup {
/**
* Remove old default documentation that is no longer present in the new import
*/
static async cleanupOldDocumentation(newStructure, user, tenant) {
console.log(`[DocumentationCleanup] Starting cleanup of old default documentation`);
// Collect all new git paths from the structure
const newGitPaths = new Set();
this.collectGitPaths(newStructure, newGitPaths);
console.log(`[DocumentationCleanup] Found ${newGitPaths.size} current git paths`);
// Find all existing default documentation for this user/tenant
const existingDocuments = await this.findExistingDefaultDocuments(user, tenant);
const existingCategories = await this.findExistingDefaultCategories(user, tenant);
const existingAssets = await this.findExistingAssets(user, tenant);
console.log(`[DocumentationCleanup] Found ${existingDocuments.length} existing documents and ${existingCategories.length} existing categories`);
// Identify documents to delete
const documentsToDelete = existingDocuments.filter((doc) => {
const gitPath = doc.get("gitPath");
return gitPath && !newGitPaths.has(gitPath);
});
// Identify categories to delete
const categoriesToDelete = existingCategories.filter((cat) => {
const gitPath = cat.get("gitPath");
return gitPath && !newGitPaths.has(gitPath);
});
console.log(`[DocumentationCleanup] Identified ${documentsToDelete.length} documents and ${categoriesToDelete.length} categories for deletion`);
// Delete old documents
let deletedDocuments = 0;
for (const doc of documentsToDelete) {
try {
console.log(`[DocumentationCleanup] Deleting document: ${doc.get("title")} (gitPath: ${doc.get("gitPath")})`);
await doc.destroy({ useMasterKey: true });
deletedDocuments++;
}
catch (error) {
console.error(`[DocumentationCleanup] Failed to delete document ${doc.id}:`, error);
}
}
// Delete old categories (delete in reverse order to handle parent-child relationships)
let deletedCategories = 0;
const sortedCategories = categoriesToDelete.sort((a, b) => {
// Sort by gitPath depth (deeper paths first) to delete children before parents
const aDepth = (a.get("gitPath") || "").split("/").length;
const bDepth = (b.get("gitPath") || "").split("/").length;
return bDepth - aDepth;
});
for (const cat of sortedCategories) {
try {
console.log(`[DocumentationCleanup] Deleting category: ${cat.get("name")} (gitPath: ${cat.get("gitPath")})`);
await cat.destroy({ useMasterKey: true });
deletedCategories++;
}
catch (error) {
console.error(`[DocumentationCleanup] Failed to delete category ${cat.id}:`, error);
}
}
// delete old assets
let deletedAssets = 0;
for (const asset of existingAssets) {
const meta = asset.get("meta") || {};
if (meta.importedByDocumentation) {
try {
console.log(`[DocumentationCleanup] Deleting asset: ${asset.get("description")} (id: ${asset.id})`);
await asset.destroy({ useMasterKey: true });
deletedAssets++;
}
catch (error) {
console.error(`[DocumentationCleanup] Failed to delete asset ${asset.id}:`, error);
}
}
}
if (deletedAssets > 0) {
console.log(`[DocumentationCleanup] Deleted ${deletedAssets} old assets imported by documentation`);
}
console.log(`[DocumentationCleanup] Cleanup complete: deleted ${deletedDocuments} documents and ${deletedCategories} categories`);
return { deletedDocuments, deletedCategories };
}
static async findExistingAssets(user, tenant) {
const query = new Parse.Query(types_1.Assets);
if (tenant) {
query.equalTo("tenant", tenant);
}
if (user) {
query.equalTo("user", user);
}
const assets = await query
// @ts-expect-error
.exists("meta.importedByDocumentation")
.findAll({ useMasterKey: true });
return assets;
}
/**
* Collect all git paths from the documentation structure
*/
static collectGitPaths(structure, gitPaths) {
// Collect file paths
for (const file of structure.allFiles) {
gitPaths.add(file.path);
}
// Collect folder paths recursively
this.collectFolderPaths(structure.root, "", gitPaths);
}
/**
* Recursively collect folder paths
*/
static collectFolderPaths(folder, currentPath, gitPaths) {
// Add current folder path (except root)
if (currentPath) {
gitPaths.add(currentPath);
}
// Recursively process subfolders
for (const [name, subfolder] of folder.subfolders) {
const subfolderPath = currentPath ? `${currentPath}/${name}` : name;
this.collectFolderPaths(subfolder, subfolderPath, gitPaths);
}
}
/**
* Find all existing default documents for the given user/tenant
*/
static async findExistingDefaultDocuments(user, tenant) {
const query = new Parse.Query(types_1.Documentation_Document)
.equalTo("isDefault", true)
.exists("gitPath"); // Only documents with gitPath (from repository)
if (tenant) {
query.equalTo("tenant", tenant);
}
if (user) {
query.equalTo("user", user);
}
try {
return await query.find({ useMasterKey: true });
}
catch (error) {
console.error(`[DocumentationCleanup] Failed to query existing documents:`, error);
return [];
}
}
/**
* Find all existing default categories for the given user/tenant
*/
static async findExistingDefaultCategories(user, tenant) {
const query = new Parse.Query(types_1.Documentation_Category)
.equalTo("isDefault", true)
.exists("gitPath"); // Only categories with gitPath (from repository)
if (tenant) {
query.equalTo("tenant", tenant);
}
if (user) {
query.equalTo("user", user);
}
try {
return await query.find({ useMasterKey: true });
}
catch (error) {
console.error(`[DocumentationCleanup] Failed to query existing categories:`, error);
return [];
}
}
}
exports.DocumentationCleanup = DocumentationCleanup;