@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
JavaScript
"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