import { Injectable } from '@nestjs/common'; import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm'; import { EntityManager, Repository, TreeRepository } from 'typeorm'; import { NewItemInput } from './dto/new-item.input'; import { Item } from './items.entity'; import { ItemModel } from './items.model'; @Injectable() export class ItemsService { constructor( @InjectRepository(Item) private itemRepository: Repository, @InjectEntityManager() private entityManager: EntityManager, ) { this.treeRepository = this.entityManager.getTreeRepository(Item); } treeRepository: TreeRepository; async getItem(id: string): Promise { return this.itemRepository.findOne(id); } async getItemParent(item: ItemModel): Promise { const childItem = await this.itemRepository.findOneOrFail(item.id, { relations: ['parent'], }); return childItem.parent; } async getItemChildren(item: ItemModel): Promise { return this.itemRepository.find({ where: { parent: item.id, }, }); } async getItemDescendents(item: ItemModel): Promise { const parentItem = await this.itemRepository.findOneOrFail(item.id, { relations: ['parent'], }); // TreeRepository.findDescendants()[0] is always the parent item return (await this.treeRepository.findDescendants(parentItem)).slice(1); } async createItem(input: NewItemInput): Promise { // must use Repository.save() for the closure table to work, // so we have to check whether the provided ID exists in the first place if (input.id && (await this.itemRepository.count({ id: input.id })) !== 0) { throw new Error('Item with this ID already exists'); } const highestId = input.id ? // nobody cares in this case null : ( await this.itemRepository.findOne({ select: ['id'], order: { id: 'DESC' }, }) )?.id || '139999999999'; const item = this.itemRepository.create({ ...input, // if id not provided, use the highest one in db +1 id: highestId ? (BigInt(highestId) + 1n).toString(10) : input.id, parent: input.parent ? await this.itemRepository.findOneOrFail(input.parent) : undefined, }); await this.itemRepository.save(item); return item; } }