UNPKG

@elsikora/nestjs-crud-automator

Version:

A library for automating the creation of CRUD operations in NestJS.

69 lines (66 loc) 3.33 kB
import { ErrorException } from '../../../../utility/error/exception.utility.js'; import { ObjectFindPropertyDescriptor } from '../../../../utility/object-find-property-descriptor.utility.js'; /** * Rejects the TypeORM relation-loader cache combination that cannot inherit a * generated mandatory read's `cache: false` root-query guarantee. */ class ApiControllerGeneratedRelationCacheContract { static assertSafe(repository, properties) { if (!this.hasRequestedRelations(properties)) { return; } const dataSourceOptions = repository.manager.connection.options; const requestedRelationLoadStrategy = this.readDataProperty(properties, "relationLoadStrategy"); const defaultRelationLoadStrategy = this.readDataProperty(dataSourceOptions, "relationLoadStrategy"); for (const strategy of [requestedRelationLoadStrategy, defaultRelationLoadStrategy]) { if (strategy && strategy !== "join" && strategy !== "query") { throw ErrorException("Generated mandatory read relationLoadStrategy must be join or query"); } } // TypeORM inherits the data-source strategy for every falsy per-query value. // eslint-disable-next-line @elsikora/typescript/prefer-nullish-coalescing const relationLoadStrategy = requestedRelationLoadStrategy || defaultRelationLoadStrategy; if (relationLoadStrategy !== "query") { return; } const cache = this.readDataProperty(dataSourceOptions, "cache"); if (cache && typeof cache === "object" && Boolean(this.readDataProperty(cache, "alwaysEnabled"))) { throw ErrorException('Generated mandatory reads cannot load relations with relationLoadStrategy "query" while TypeORM query cache is always enabled'); } } static hasRequestedRelations(properties) { const descriptor = ObjectFindPropertyDescriptor(properties, "relations"); if (!descriptor) { return false; } if (!("value" in descriptor)) { return true; } const relationsValue = descriptor.value; if (Array.isArray(relationsValue)) { return relationsValue.length > 0; } if (!relationsValue || typeof relationsValue !== "object") { return false; } for (const key of Reflect.ownKeys(relationsValue)) { const relationDescriptor = Object.getOwnPropertyDescriptor(relationsValue, key); if (!relationDescriptor || !("value" in relationDescriptor) || relationDescriptor.value === true || typeof relationDescriptor.value === "string" || (relationDescriptor.value !== null && typeof relationDescriptor.value === "object")) { return true; } } return false; } static readDataProperty(source, key) { const descriptor = ObjectFindPropertyDescriptor(source, key); if (!descriptor) { return undefined; } if (!("value" in descriptor)) { throw ErrorException(`Generated mandatory read option ${String(key)} must be a data property`); } return descriptor.value; } } export { ApiControllerGeneratedRelationCacheContract }; //# sourceMappingURL=relation-cache-contract.class.js.map