UNPKG

n8n

Version:

n8n Workflow Automation Tool

196 lines 9.46 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FolderService = void 0; const di_1 = require("@n8n/di"); const n8n_workflow_1 = require("n8n-workflow"); const folder_1 = require("../databases/entities/folder"); const folder_tag_mapping_repository_1 = require("../databases/repositories/folder-tag-mapping.repository"); const folder_repository_1 = require("../databases/repositories/folder.repository"); const workflow_repository_1 = require("../databases/repositories/workflow.repository"); const folder_not_found_error_1 = require("../errors/folder-not-found.error"); let FolderService = class FolderService { constructor(folderRepository, folderTagMappingRepository, workflowRepository) { this.folderRepository = folderRepository; this.folderTagMappingRepository = folderTagMappingRepository; this.workflowRepository = workflowRepository; } async createFolder({ parentFolderId, name }, projectId) { let parentFolder = null; if (parentFolderId) { parentFolder = await this.findFolderInProjectOrFail(parentFolderId, projectId); } const folderEntity = this.folderRepository.create({ name, homeProject: { id: projectId }, parentFolder, }); const { homeProject, ...folder } = await this.folderRepository.save(folderEntity); return folder; } async updateFolder(folderId, projectId, { name, tagIds, parentFolderId }) { await this.findFolderInProjectOrFail(folderId, projectId); if (name) { await this.folderRepository.update({ id: folderId }, { name }); } if (tagIds) { await this.folderTagMappingRepository.overwriteTags(folderId, tagIds); } if (parentFolderId) { if (folderId === parentFolderId) { throw new n8n_workflow_1.UserError('Cannot set a folder as its own parent'); } if (parentFolderId !== n8n_workflow_1.PROJECT_ROOT) { await this.findFolderInProjectOrFail(parentFolderId, projectId); } await this.folderRepository.update({ id: folderId }, { parentFolder: parentFolderId !== n8n_workflow_1.PROJECT_ROOT ? { id: parentFolderId } : null }); } } async findFolderInProjectOrFail(folderId, projectId, em) { try { return await this.folderRepository.findOneOrFailFolderInProject(folderId, projectId, em); } catch { throw new folder_not_found_error_1.FolderNotFoundError(folderId); } } async getFolderTree(folderId, projectId) { await this.findFolderInProjectOrFail(folderId, projectId); const escapedParentFolderId = this.folderRepository .createQueryBuilder() .escape('parentFolderId'); const baseQuery = this.folderRepository .createQueryBuilder('folder') .select('folder.id', 'id') .addSelect('folder.parentFolderId', 'parentFolderId') .where('folder.id = :folderId', { folderId }); const recursiveQuery = this.folderRepository .createQueryBuilder('f') .select('f.id', 'id') .addSelect('f.parentFolderId', 'parentFolderId') .innerJoin('folder_path', 'fp', `f.id = fp.${escapedParentFolderId}`); const mainQuery = this.folderRepository .createQueryBuilder('folder') .select('folder.id', 'folder_id') .addSelect('folder.name', 'folder_name') .addSelect('folder.parentFolderId', 'folder_parent_folder_id') .addCommonTableExpression(`${baseQuery.getQuery()} UNION ALL ${recursiveQuery.getQuery()}`, 'folder_path', { recursive: true }) .where((qb) => { const subQuery = qb.subQuery().select('fp.id').from('folder_path', 'fp').getQuery(); return `folder.id IN ${subQuery}`; }) .setParameters({ folderId, }); const result = await mainQuery.getRawMany(); return this.transformFolderPathToTree(result); } async deleteFolder(folderId, projectId, { transferToFolderId }) { await this.findFolderInProjectOrFail(folderId, projectId); if (!transferToFolderId) { await this.folderRepository.delete({ id: folderId }); return; } if (folderId === transferToFolderId) { throw new n8n_workflow_1.UserError('Cannot transfer folder contents to the folder being deleted'); } if (transferToFolderId !== n8n_workflow_1.PROJECT_ROOT) { await this.findFolderInProjectOrFail(transferToFolderId, projectId); } return await this.folderRepository.manager.transaction(async (tx) => { await this.folderRepository.moveAllToFolder(folderId, transferToFolderId, tx); await this.workflowRepository.moveAllToFolder(folderId, transferToFolderId, tx); await tx.delete(folder_1.Folder, { id: folderId }); return; }); } async transferAllFoldersToProject(fromProjectId, toProjectId, tx) { return await this.folderRepository.transferAllFoldersToProject(fromProjectId, toProjectId, tx); } transformFolderPathToTree(flatPath) { if (!flatPath || flatPath.length === 0) { return []; } const folderMap = new Map(); flatPath.forEach((folder) => { folderMap.set(folder.folder_id, { id: folder.folder_id, name: folder.folder_name, children: [], }); }); let rootNode = null; flatPath.forEach((folder) => { const currentNode = folderMap.get(folder.folder_id); if (folder.folder_parent_folder_id && folderMap.has(folder.folder_parent_folder_id)) { const parentNode = folderMap.get(folder.folder_parent_folder_id); parentNode.children = [currentNode]; } else { rootNode = currentNode; } }); return rootNode ? [rootNode] : []; } async getFolderAndWorkflowCount(folderId, projectId) { await this.findFolderInProjectOrFail(folderId, projectId); const baseQuery = this.folderRepository .createQueryBuilder('folder') .select('folder.id', 'id') .where('folder.id = :folderId', { folderId }); const recursiveQuery = this.folderRepository .createQueryBuilder('f') .select('f.id', 'id') .innerJoin('folder_path', 'fp', 'f.parentFolderId = fp.id'); const subFolderCountQuery = this.folderRepository .createQueryBuilder('folder') .addCommonTableExpression(`${baseQuery.getQuery()} UNION ALL ${recursiveQuery.getQuery()}`, 'folder_path', { recursive: true }) .select('COUNT(DISTINCT folder.id) - 1', 'count') .where((qb) => { const subQuery = qb.subQuery().select('fp.id').from('folder_path', 'fp').getQuery(); return `folder.id IN ${subQuery}`; }) .setParameters({ folderId, }); const workflowCountQuery = this.workflowRepository .createQueryBuilder('workflow') .select('COUNT(workflow.id)', 'count') .where((qb) => { const folderQuery = qb.subQuery().from('folder_path', 'fp').select('fp.id').getQuery(); return `workflow.parentFolderId IN ${folderQuery}`; }) .addCommonTableExpression(`${baseQuery.getQuery()} UNION ALL ${recursiveQuery.getQuery()}`, 'folder_path', { recursive: true }) .setParameters({ folderId, }); const [subFolderResult, workflowResult] = await Promise.all([ subFolderCountQuery.getRawOne(), workflowCountQuery.getRawOne(), ]); return { totalSubFolders: parseInt(subFolderResult?.count ?? '0', 10), totalWorkflows: parseInt(workflowResult?.count ?? '0', 10), }; } async getManyAndCount(projectId, options) { options.filter = { ...options.filter, projectId }; return await this.folderRepository.getManyAndCount(options); } }; exports.FolderService = FolderService; exports.FolderService = FolderService = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [folder_repository_1.FolderRepository, folder_tag_mapping_repository_1.FolderTagMappingRepository, workflow_repository_1.WorkflowRepository]) ], FolderService); //# sourceMappingURL=folder.service.js.map