UNPKG

@algochad/prisma-core

Version:

A comprehensive NestJS library that provides EF-Core-like operations using Prisma and GraphQL. Features LINQ-style query builders, advanced data manipulation, GraphQL integration with genql, and a unified API for both Prisma and GraphQL operations. Includ

393 lines 12.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PrismaQueryBuilder = void 0; const collections_1 = require("../../collections"); const prisma_queryable_1 = require("../../collections/prisma/prisma-queryable"); class PrismaQueryBuilder { prismaModel; whereClause = {}; selectClause; includeClause; orderByClause; takeClause; skipClause; modelName; constructor(prismaModel, modelName) { this.prismaModel = prismaModel; this.modelName = modelName; } static create(prismaModel, expectedResult) { return new PrismaQueryBuilder(prismaModel); } static createFrom(builder, prismaModel, expectedResult) { return new PrismaQueryBuilder(prismaModel); } ContextFactory() { return this.NewContext(); } NewContext() { return new PrismaQueryBuilder(this.prismaModel, this.modelName); } resetQueryState() { this.whereClause = {}; this.selectClause = undefined; this.includeClause = undefined; this.orderByClause = undefined; this.takeClause = undefined; this.skipClause = undefined; } Where(where) { this.whereClause = { ...this.whereClause, ...where }; return this; } Select(select, expectedResult) { this.selectClause = select; return this; } SelectAll() { this.selectClause = undefined; return this; } SelectAs(select) { return new TypedSelector(this, select); } Include(include, expectedResult) { if (this.includeClause && typeof this.includeClause === 'object' && typeof include === 'object') { this.includeClause = this.mergeIncludes(this.includeClause, include); } else { this.includeClause = include; } return this; } mergeIncludes(existing, newInclude) { if (!existing || typeof existing !== 'object') return newInclude; if (!newInclude || typeof newInclude !== 'object') return existing; const merged = { ...existing }; for (const [key, value] of Object.entries(newInclude)) { if (key in merged) { const existingValue = merged[key]; if (typeof existingValue === 'boolean' && typeof value === 'object') { merged[key] = value; } else if (typeof value === 'boolean' && typeof existingValue === 'object') { continue; } else if (typeof existingValue === 'object' && typeof value === 'object' && existingValue !== null && value !== null) { merged[key] = this.mergeIncludes(existingValue, value); } else { merged[key] = value; } } else { merged[key] = value; } } return merged; } OrderBy(orderBy) { this.orderByClause = orderBy; return this; } Take(n) { this.takeClause = n; return this; } Skip(n) { this.skipClause = n; return this; } async ToArray() { const data = await this.prismaModel.findMany({ where: this.whereClause, select: this.selectClause, include: this.includeClause, orderBy: this.orderByClause, take: this.takeClause, skip: this.skipClause, }); this.resetQueryState(); return data; } async First() { const result = await this.prismaModel.findFirst({ where: this.whereClause, select: this.selectClause, include: this.includeClause, orderBy: this.orderByClause, }); this.resetQueryState(); return result; } async Project(selector) { return this.ToEnumerable().then((enumerable) => enumerable.Select(selector)); } async GroupBy(keySelector, elementSelector, resultSelector) { const groups = new Map(); const data = await this.ExecuteQueryAndMap(); data.forEach((item) => { const key = keySelector(item); const element = elementSelector ? elementSelector(item) : item; if (!groups.has(key)) { groups.set(key, []); } groups.get(key).push(element); }); if (resultSelector) { return Array.from(groups.entries()).map(([key, group]) => resultSelector(key, group)); } return Array.from(groups.values()); } async ExecuteQueryAndMap() { const data = await this.prismaModel.findMany({ where: this.whereClause, select: this.selectClause, include: this.includeClause, orderBy: this.orderByClause, take: this.takeClause, skip: this.skipClause, }); this.resetQueryState(); return data; } async ToList() { const data = await this.ExecuteQueryAndMap(); this.resetQueryState(); return new collections_1.List(data); } async ToEnumerable() { const data = await this.ExecuteQueryAndMap(); this.resetQueryState(); return new collections_1.Enumerable(data); } async Execute() { const data = await this.ExecuteQueryAndMap(); this.resetQueryState(); return collections_1.AsyncEnumerable.fromArray(data); } async ToAsyncEnumerable() { const data = await this.prismaModel.findMany({ where: this.whereClause, select: this.selectClause, include: this.includeClause, orderBy: this.orderByClause, take: this.takeClause, skip: this.skipClause, }); this.resetQueryState(); return collections_1.AsyncEnumerable.fromArray(data); } async ToEnumerableAsync() { return await this.ToEnumerable(); } async AsEnumerable() { return await this.ToEnumerable(); } async ToArrayAsync() { return await this.ToArray(); } async FirstOrDefault() { const result = await this.First(); return result === null ? undefined : result; } async Single() { const whereKeys = Object.keys(this.whereClause || {}); const isUnique = whereKeys.length === 1 && (whereKeys[0] === 'id' || whereKeys[0].endsWith('Id')); if (isUnique) { const result = await this.prismaModel.findUnique({ where: this.whereClause, select: this.selectClause, include: this.includeClause, }); this.resetQueryState(); return result; } else { const results = await this.prismaModel.findMany({ where: this.whereClause, select: this.selectClause, include: this.includeClause, }); this.resetQueryState(); if (results.length === 1) return results[0]; if (results.length === 0) return null; throw new Error('Single() called but more than one result found'); } } async Count() { const count = await this.prismaModel.count({ where: this.whereClause, }); this.resetQueryState(); return count; } async Exists() { const count = await this.Count(); return count > 0; } async Any() { return this.Exists(); } async Min(field) { const result = await this.prismaModel.aggregate({ where: this.whereClause, _min: { [field]: true }, }); this.resetQueryState(); return result._min[field]; } async Max(field) { const result = await this.prismaModel.aggregate({ where: this.whereClause, _max: { [field]: true }, }); this.resetQueryState(); return result._max[field]; } async Sum(field) { const result = await this.prismaModel.aggregate({ where: this.whereClause, _sum: { [field]: true }, }); this.resetQueryState(); return result._sum[field] || 0; } async Avg(field) { const result = await this.prismaModel.aggregate({ where: this.whereClause, _avg: { [field]: true }, }); this.resetQueryState(); return result._avg[field] || 0; } async Paginate(pageNumber, pageSize) { const skip = (pageNumber - 1) * pageSize; const take = pageSize; const [data, total] = await Promise.all([ this.prismaModel.findMany({ where: this.whereClause, select: this.selectClause, include: this.includeClause, orderBy: this.orderByClause, skip, take, }), this.prismaModel.count({ where: this.whereClause }), ]); this.resetQueryState(); return { data, total, page: pageNumber, pageSize, }; } AsQueryable() { const expression = { where: this.whereClause, select: this.selectClause, include: this.includeClause, orderBy: this.orderByClause ? [this.orderByClause] : undefined, take: this.takeClause, skip: this.skipClause, isTracking: true, modelName: this.modelName, }; const provider = new prisma_queryable_1.PrismaQueryProvider(this.prismaModel, this.modelName); return new prisma_queryable_1.PrismaQueryable(provider, expression); } AsNoTrackingQueryable() { const expression = { where: this.whereClause, select: this.selectClause, include: this.includeClause, orderBy: this.orderByClause ? [this.orderByClause] : undefined, take: this.takeClause, skip: this.skipClause, isTracking: false, modelName: this.modelName, }; const provider = new prisma_queryable_1.PrismaQueryProvider(this.prismaModel, this.modelName); return new prisma_queryable_1.PrismaQueryable(provider, expression); } buildExpression() { return { where: this.whereClause, select: this.selectClause, include: this.includeClause, orderBy: this.orderByClause ? [this.orderByClause] : undefined, take: this.takeClause, skip: this.skipClause, isTracking: true, modelName: this.modelName, }; } static From(source) { const builder = new PrismaQueryBuilder(null); return builder; } async AsAsyncEnumerable() { return this.Execute(); } CopyTo(newPrismaModel) { const newBuilder = new PrismaQueryBuilder(newPrismaModel); return newBuilder; } get Provider() { return new prisma_queryable_1.PrismaQueryProvider(this.prismaModel, this.modelName); } get Expression() { return { where: this.whereClause, select: this.selectClause, include: this.includeClause, orderBy: this.orderByClause ? [this.orderByClause] : undefined, take: this.takeClause, skip: this.skipClause, modelName: this.modelName, }; } } exports.PrismaQueryBuilder = PrismaQueryBuilder; class TypedSelector { builder; select; constructor(builder, select) { this.builder = builder; this.select = select; } As() { this.builder.selectClause = this.select; return this.builder; } Inferred() { this.builder.selectClause = this.select; return this.builder; } } class SelectBuilder { builder; constructor(builder) { this.builder = builder; } Fields(select) { this.builder.selectClause = select; return this.builder; } } //# sourceMappingURL=prisma-query-builder.js.map