nestjs-prisma-base
Version:
A comprehensive NestJS package providing base classes, utilities, and decorators for building CRUD APIs with Prisma ORM integration, featuring pagination, search, filtering, relation loading, configurable DTOs, and modular composition capabilities.
134 lines • 5.14 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RelationValidator = void 0;
class RelationValidator {
static validateIncludes(requestedIncludes, config) {
const result = {
validatedIncludes: {},
invalidKeys: [],
depthExceeded: false,
};
if (!config) {
if (Array.isArray(requestedIncludes)) {
result.validatedIncludes = this.arrayToIncludeObject(requestedIncludes);
}
else if (typeof requestedIncludes === 'object' && requestedIncludes !== null) {
result.validatedIncludes = requestedIncludes;
}
return result;
}
if (config.defaultIncludes) {
result.validatedIncludes = { ...config.defaultIncludes };
}
if (requestedIncludes) {
let includesToProcess;
if (Array.isArray(requestedIncludes)) {
includesToProcess = this.arrayToIncludeObject(requestedIncludes);
}
else if (typeof requestedIncludes === 'object') {
includesToProcess = requestedIncludes;
}
else {
return result;
}
for (const [key, value] of Object.entries(includesToProcess)) {
if (this.isValidInclude(key, config)) {
if (config.customIncludes && config.customIncludes[key]) {
result.validatedIncludes[key] = config.customIncludes[key];
}
else {
result.validatedIncludes[key] = value;
}
}
else {
result.invalidKeys.push(key);
}
}
}
if (config.maxDepth && config.maxDepth > 0) {
const depth = this.calculateDepth(result.validatedIncludes);
if (depth > config.maxDepth) {
result.depthExceeded = true;
result.validatedIncludes = this.limitDepth(result.validatedIncludes, config.maxDepth);
}
}
return result;
}
static arrayToIncludeObject(includes) {
const result = {};
for (const include of includes) {
if (typeof include === 'string' && include.trim()) {
result[include.trim()] = true;
}
}
return result;
}
static isValidInclude(key, config) {
if (!config.availableIncludes || config.availableIncludes.length === 0) {
return true;
}
return config.availableIncludes.includes(key);
}
static calculateDepth(includes, currentDepth = 0) {
let maxDepth = currentDepth;
for (const value of Object.values(includes)) {
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
if ('include' in value && typeof value.include === 'object') {
const nestedDepth = this.calculateDepth(value.include, currentDepth + 1);
maxDepth = Math.max(maxDepth, nestedDepth);
}
else if (!('select' in value) && !('where' in value)) {
const nestedDepth = this.calculateDepth(value, currentDepth + 1);
maxDepth = Math.max(maxDepth, nestedDepth);
}
}
}
return maxDepth;
}
static limitDepth(includes, maxDepth, currentDepth = 0) {
if (currentDepth >= maxDepth) {
return {};
}
const result = {};
for (const [key, value] of Object.entries(includes)) {
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
if ('include' in value && typeof value.include === 'object') {
result[key] = {
...value,
include: this.limitDepth(value.include, maxDepth, currentDepth + 1),
};
}
else if (!('select' in value) && !('where' in value)) {
result[key] = this.limitDepth(value, maxDepth, currentDepth + 1);
}
else {
result[key] = value;
}
}
else {
result[key] = value;
}
}
return result;
}
static parseIncludeString(includeString) {
if (!includeString || typeof includeString !== 'string') {
return [];
}
return includeString
.split(',')
.map((item) => item.trim())
.filter((item) => item.length > 0);
}
static mergeIncludes(defaultIncludes, requestedIncludes) {
const merged = { ...(defaultIncludes || {}) };
if (requestedIncludes) {
for (const [key, value] of Object.entries(requestedIncludes)) {
merged[key] = value;
}
}
return merged;
}
}
exports.RelationValidator = RelationValidator;
//# sourceMappingURL=relation-validator.js.map