@elsikora/nestjs-crud-automator
Version:
A library for automating the creation of CRUD operations in NestJS.
69 lines (66 loc) • 3.33 kB
JavaScript
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