n8n
Version:
n8n Workflow Automation Tool
196 lines • 9.46 kB
JavaScript
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
;