UNPKG

n8n

Version:

n8n Workflow Automation Tool

162 lines • 6.68 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.TagService = void 0; const db_1 = require("@n8n/db"); const di_1 = require("@n8n/di"); const typeorm_1 = require("@n8n/typeorm"); const external_hooks_1 = require("../external-hooks"); const generic_helpers_1 = require("../generic-helpers"); function dedupeNamesPreservingCase(names) { const seen = new Set(); const result = []; for (const raw of names) { const trimmed = raw.trim(); if (trimmed.length === 0) continue; const key = trimmed.toLowerCase(); if (seen.has(key)) continue; seen.add(key); result.push(trimmed); } return result; } function isUniqueConstraintViolation(error) { if (!(error instanceof typeorm_1.QueryFailedError)) return false; const driver = error.driverError; const code = driver && typeof driver.code !== 'undefined' ? String(driver.code) : undefined; if (code === '23505' || code === 'SQLITE_CONSTRAINT_UNIQUE') return true; return code === 'SQLITE_CONSTRAINT' && /UNIQUE constraint/i.test(error.message); } let TagService = class TagService { constructor(externalHooks, tagRepository) { this.externalHooks = externalHooks; this.tagRepository = tagRepository; } toEntity(attrs) { attrs.name = attrs.name.trim(); return this.tagRepository.create(attrs); } async save(tag, actionKind) { await (0, generic_helpers_1.validateEntity)(tag); const action = (actionKind[0].toUpperCase() + actionKind.slice(1)); await this.externalHooks.run(`tag.before${action}`, [tag]); const savedTag = this.tagRepository.save(tag, { transaction: false }); await this.externalHooks.run(`tag.after${action}`, [tag]); return await savedTag; } async delete(id) { await this.externalHooks.run('tag.beforeDelete', [id]); const deleteResult = this.tagRepository.delete(id); await this.externalHooks.run('tag.afterDelete', [id]); return await deleteResult; } async getAll(options) { if (options?.withUsageCount) { const qb = this.tagRepository .createQueryBuilder('tag') .select(['tag.id', 'tag.name', 'tag.createdAt', 'tag.updatedAt']) .loadRelationCountAndMap('tag.usageCount', 'tag.workflowMappings', 'wm', (qb2) => qb2.leftJoin('wm.workflows', 'workflow').where('workflow.isArchived = :isArchived', { isArchived: false, })); if (options.orderByName) qb.orderBy('tag.name', 'ASC'); if (options.limit !== undefined) qb.limit(options.limit); const tags = await qb.getMany(); return tags; } return await this.tagRepository.find({ select: ['id', 'name', 'createdAt', 'updatedAt'], ...(options?.orderByName ? { order: { name: 'ASC' } } : {}), ...(options?.limit !== undefined ? { take: options.limit } : {}), }); } async getPaginated({ offset, limit }) { const [data, count] = await this.tagRepository.findAndCount({ skip: offset, take: limit, select: ['id', 'name', 'createdAt', 'updatedAt'], order: { createdAt: 'ASC', id: 'ASC' }, }); return { data, count }; } async getById(id) { return await this.tagRepository.findOneOrFail({ where: { id }, }); } async listWithUsageCount({ limit }) { const [data, totalCount] = await Promise.all([ this.getAll({ withUsageCount: true, limit, orderByName: true }), this.tagRepository.count(), ]); return { data, totalCount }; } sortByRequestOrder(tags, { requestOrder }) { const tagMap = tags.reduce((acc, tag) => { acc[tag.id] = tag; return acc; }, {}); return requestOrder.map((tagId) => tagMap[tagId]); } async findByNames(names) { const uniqueNames = dedupeNamesPreservingCase(names); if (uniqueNames.length === 0) return []; const existing = await this.tagRepository.find({ where: { name: (0, typeorm_1.In)(uniqueNames) } }); const existingByName = new Map(existing.map((t) => [t.name, t])); const result = []; for (const name of uniqueNames) { const hit = existingByName.get(name); if (hit) result.push(hit); } return result; } async findOrCreateByNames(names) { const uniqueNames = dedupeNamesPreservingCase(names); if (uniqueNames.length === 0) return []; const existing = await this.tagRepository.find({ where: { name: (0, typeorm_1.In)(uniqueNames) } }); const existingByName = new Map(existing.map((t) => [t.name, t])); const result = []; for (const name of uniqueNames) { const hit = existingByName.get(name); if (hit) { result.push(hit); continue; } try { const created = await this.save(this.toEntity({ name }), 'create'); result.push(created); } catch (error) { if (!isUniqueConstraintViolation(error)) throw error; const raced = await this.tagRepository.findOneBy({ name }); if (!raced) throw error; result.push(raced); } } return result; } }; exports.TagService = TagService; exports.TagService = TagService = __decorate([ (0, di_1.Service)(), __metadata("design:paramtypes", [external_hooks_1.ExternalHooks, db_1.TagRepository]) ], TagService); //# sourceMappingURL=tag.service.js.map