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

832 lines 28 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InMemoryGraphQLQueryable = exports.GraphQLOrderedQueryable = exports.GraphQLQueryable = exports.GraphQLQueryProvider = void 0; const async_enumerable_1 = require("../linq/async-enumerable"); const enumerable_1 = require("../linq/enumerable"); const list_1 = require("../linq/list"); class GraphQLQueryProvider { genqlClient; operationName; operationType; constructor(genqlClient, operationName, operationType = 'query') { this.genqlClient = genqlClient; this.operationName = operationName; this.operationType = operationType; } async Execute(expression) { const query = this.buildGenqlQuery(expression); let results; switch (expression.operationType || this.operationType) { case 'mutation': if (!this.genqlClient.mutation) { throw new Error('Mutation not supported by this GraphQL client'); } results = await this.genqlClient.mutation(query); break; case 'subscription': if (!this.genqlClient.subscription) { throw new Error('Subscription not supported by this GraphQL client'); } const subscription = this.genqlClient.subscription(query); const { value } = await subscription.next(); results = value; break; default: results = await this.genqlClient.query(query); } let data = results[this.operationName]; if (expression.inMemoryPredicates && expression.inMemoryPredicates.length > 0) { if (Array.isArray(data)) { for (const predicate of expression.inMemoryPredicates) { if (predicate) { data = data.filter(predicate); } } } } return data; } buildGenqlQuery(expression) { const query = {}; const operationQuery = {}; const args = {}; if (expression.where) { Object.assign(args, expression.where); } if (expression.args) { Object.assign(args, expression.args); } if (expression.first !== undefined) { args.first = expression.first; } if (expression.skip !== undefined) { args.skip = expression.skip; } if (expression.orderBy && expression.orderBy.length > 0) { args.orderBy = expression.orderBy; } if (Object.keys(args).length > 0) { operationQuery.__args = args; } if (expression.select) { Object.assign(operationQuery, expression.select); } else { operationQuery.__scalar = true; } query[this.operationName] = operationQuery; return query; } CreateQuery(expression) { return new GraphQLQueryable(this, expression); } } exports.GraphQLQueryProvider = GraphQLQueryProvider; class GraphQLQueryable { provider; expression; elementType; constructor(provider, expression, elementType) { this.provider = provider; this.expression = expression || {}; this.elementType = elementType; } get Provider() { return this.provider; } get Expression() { return this.expression; } get ElementType() { return this.elementType; } createNew(newExpression) { const mergedExpression = { ...this.expression, ...newExpression }; return new GraphQLQueryable(this.provider, mergedExpression, this.elementType); } WhereFilter(where) { const existingWhere = this.expression.where; let finalWhere; if (existingWhere && typeof existingWhere === 'object' && typeof where === 'object') { finalWhere = { ...existingWhere, ...where }; } else { finalWhere = where; } return this.createNew({ where: finalWhere }); } SelectFields(select) { return this.createNew({ select: select }); } Include(include) { throw new Error('Include is not supported in GraphQL. Use SelectFields instead to specify the fields you want to retrieve.'); } OrderBy(orderBy) { return new GraphQLOrderedQueryable(this.provider, { ...this.expression, orderBy: [orderBy] }, this.elementType); } SelectMany(selector) { const resultData = this.ToArrayAsync().then(async (items) => { const results = []; for (const item of items) { const selected = selector(item); if ('ToArrayAsync' in selected) { const subResults = await selected.ToArrayAsync(); results.push(...subResults); } else { for await (const subItem of selected) { results.push(subItem); } } } return results; }); return new InMemoryGraphQLQueryable(resultData); } GroupBy(keySelector, elementSelector, resultSelector) { const resultData = this.ToArrayAsync().then((items) => { const groups = new Map(); for (const item of items) { const key = keySelector(item); const element = elementSelector ? elementSelector(item) : item; if (!groups.has(key)) { groups.set(key, []); } groups.get(key).push(element); } const results = []; for (const [key, elements] of groups.entries()) { if (resultSelector) { const group = new InMemoryGraphQLQueryable(elements); results.push(resultSelector(key, group)); } else { results.push({ Key: key, Values: elements }); } } return results; }); return new InMemoryGraphQLQueryable(resultData); } Join(inner, outerKeySelector, innerKeySelector, resultSelector) { const resultData = Promise.all([ this.ToArrayAsync(), 'ToArrayAsync' in inner ? inner.ToArrayAsync() : Promise.resolve([]), ]).then(([outerItems, innerItems]) => { const results = []; for (const outerItem of outerItems) { const outerKey = outerKeySelector(outerItem); for (const innerItem of innerItems) { const innerKey = innerKeySelector(innerItem); if (outerKey === innerKey) { results.push(resultSelector(outerItem, innerItem)); } } } return results; }); return new InMemoryGraphQLQueryable(resultData); } Union(other) { const resultData = Promise.all([ this.ToArrayAsync(), 'ToArrayAsync' in other ? other.ToArrayAsync() : Promise.resolve([]), ]).then(([thisItems, otherItems]) => { const seen = new Set(); const results = []; for (const item of [...thisItems, ...otherItems]) { const key = JSON.stringify(item); if (!seen.has(key)) { seen.add(key); results.push(item); } } return results; }); return new InMemoryGraphQLQueryable(resultData); } Intersect(other) { const resultData = Promise.all([ this.ToArrayAsync(), 'ToArrayAsync' in other ? other.ToArrayAsync() : Promise.resolve([]), ]).then(([thisItems, otherItems]) => { const otherSet = new Set(otherItems.map((item) => JSON.stringify(item))); const results = []; const seen = new Set(); for (const item of thisItems) { const key = JSON.stringify(item); if (otherSet.has(key) && !seen.has(key)) { seen.add(key); results.push(item); } } return results; }); return new InMemoryGraphQLQueryable(resultData); } Except(other) { const resultData = Promise.all([ this.ToArrayAsync(), 'ToArrayAsync' in other ? other.ToArrayAsync() : Promise.resolve([]), ]).then(([thisItems, otherItems]) => { const otherSet = new Set(otherItems.map((item) => JSON.stringify(item))); const results = []; const seen = new Set(); for (const item of thisItems) { const key = JSON.stringify(item); if (!otherSet.has(key) && !seen.has(key)) { seen.add(key); results.push(item); } } return results; }); return new InMemoryGraphQLQueryable(resultData); } Take(count) { return this.createNew({ first: count }); } Skip(count) { return this.createNew({ skip: count }); } Distinct(keySelector) { return this.createNew({ distinct: keySelector ? [keySelector] : true, }); } Where = this.WhereFilter; Select = this.SelectFields; async ExecuteAsync() { return await this.ToArrayAsync(); } async ToArrayAsync() { return await this.provider.Execute(this.expression); } async ToListAsync() { const array = await this.ToArrayAsync(); return new list_1.List(array); } async FirstAsync(predicate) { if (predicate) { const items = await this.ToArrayAsync(); for (const item of items) { if (await predicate(item)) return item; } throw new Error('No matching element found'); } else { const results = await this.createNew({ first: 1, }).ToArrayAsync(); if (results.length === 0) { throw new Error('Sequence contains no elements'); } return results[0]; } } async FirstOrDefaultAsync(predicate) { try { return await this.FirstAsync(predicate); } catch { return undefined; } } async LastAsync(predicate) { const items = await this.ToArrayAsync(); if (predicate) { for (let i = items.length - 1; i >= 0; i--) { if (await predicate(items[i])) return items[i]; } throw new Error('No matching element found'); } if (items.length === 0) { throw new Error('Sequence contains no elements'); } return items[items.length - 1]; } async LastOrDefaultAsync(predicate) { try { return await this.LastAsync(predicate); } catch { return undefined; } } async SingleAsync(predicate) { const items = await this.ToArrayAsync(); let found; let count = 0; for (const item of items) { if (!predicate || (await predicate(item))) { found = item; count++; if (count > 1) { throw new Error('Sequence contains more than one element'); } } } if (count === 0) { throw new Error('Sequence contains no elements'); } return found; } async SingleOrDefaultAsync(predicate) { try { return await this.SingleAsync(predicate); } catch (error) { if (error.message.includes('more than one element')) { throw error; } return undefined; } } async CountAsync(predicate) { if (predicate) { const items = await this.ToArrayAsync(); let count = 0; for (const item of items) { if (await predicate(item)) count++; } return count; } else { const items = await this.ToArrayAsync(); return items.length; } } async AnyAsync(predicate) { if (predicate) { const items = await this.ToArrayAsync(); for (const item of items) { if (await predicate(item)) return true; } return false; } else { const results = await this.createNew({ first: 1, }).ToArrayAsync(); return results.length > 0; } } async AllAsync(predicate) { const items = await this.ToArrayAsync(); for (const item of items) { if (!(await predicate(item))) return false; } return true; } async MinAsync(selector) { const items = await this.ToArrayAsync(); if (items.length === 0) { throw new Error('Sequence contains no elements'); } if (selector) { return items .map(selector) .reduce((min, current) => (current < min ? current : min)); } return items.reduce((min, current) => (current < min ? current : min)); } async MaxAsync(selector) { const items = await this.ToArrayAsync(); if (items.length === 0) { throw new Error('Sequence contains no elements'); } if (selector) { return items .map(selector) .reduce((max, current) => (current > max ? current : max)); } return items.reduce((max, current) => (current > max ? current : max)); } async SumAsync(selector) { const items = await this.ToArrayAsync(); return items .map(selector || ((x) => x)) .reduce((sum, current) => sum + current, 0); } async AverageAsync(selector) { const items = await this.ToArrayAsync(); const values = items.map(selector || ((x) => x)); return (values.reduce((sum, current) => sum + current, 0) / values.length); } async LongCountAsync(predicate) { return await this.CountAsync(predicate); } async AggregateAsync(seed, func) { const items = await this.ToArrayAsync(); let accumulator = seed; for (const item of items) { accumulator = await func(accumulator, item); } return accumulator; } async ContainsAsync(item) { const items = await this.ToArrayAsync(); return items.includes(item); } async ForEachAsync(action) { const items = await this.ToArrayAsync(); for (const item of items) { await action(item); } } async ToEnumerable() { const array = await this.ToArrayAsync(); return new enumerable_1.Enumerable(array); } async AsEnumerable() { return this.ToEnumerable(); } async AsAsyncEnumerable() { const array = await this.ToArrayAsync(); return new async_enumerable_1.AsyncEnumerable(array); } async ToEnumerableAsync() { return this.ToEnumerable(); } async ToAsyncEnumerable() { return this.AsAsyncEnumerable(); } } exports.GraphQLQueryable = GraphQLQueryable; class GraphQLOrderedQueryable extends GraphQLQueryable { Take(count) { return new GraphQLOrderedQueryable(this.provider, { ...this.expression, first: count }, this.elementType); } Skip(count) { return new GraphQLOrderedQueryable(this.provider, { ...this.expression, skip: count }, this.elementType); } Distinct(keySelector) { return new GraphQLOrderedQueryable(this.provider, { ...this.expression, distinct: keySelector ? [keySelector] : true, }, this.elementType); } ThenBy(orderBy) { const currentOrderBy = this.expression.orderBy || []; return new GraphQLOrderedQueryable(this.provider, { ...this.expression, orderBy: [...currentOrderBy, orderBy], }, this.elementType); } ThenByDescending(orderBy) { const currentOrderBy = this.expression.orderBy || []; return new GraphQLOrderedQueryable(this.provider, { ...this.expression, orderBy: [...currentOrderBy, orderBy], }, this.elementType); } } exports.GraphQLOrderedQueryable = GraphQLOrderedQueryable; class InMemoryGraphQLQueryable { data; constructor(data) { this.data = data; } get Provider() { throw new Error('InMemoryGraphQLQueryable does not support Provider'); } get Expression() { return null; } get ElementType() { return null; } WhereFilter(where) { throw new Error('WhereFilter not supported in InMemoryGraphQLQueryable'); } SelectFields(select) { throw new Error('SelectFields not supported in InMemoryGraphQLQueryable'); } Include(include) { throw new Error('Include is not supported in GraphQL. Use SelectFields instead to specify the fields you want to retrieve.'); } OrderBy(orderBy) { throw new Error('OrderBy not supported in InMemoryGraphQLQueryable'); } SelectMany(selector) { const newData = this.resolveData().then(async (items) => { const results = []; for (const item of items) { const result = selector(item); if (result && typeof result.ToArrayAsync === 'function') { const arr = await result.ToArrayAsync(); results.push(...arr); } else if (result && typeof result.ToArrayAsync === 'function') { const arr = await result.ToArrayAsync(); results.push(...arr); } } return results; }); return new InMemoryGraphQLQueryable(newData); } GroupBy(keySelector, elementSelector, resultSelector) { const newData = this.resolveData().then((items) => { const groups = new Map(); for (const item of items) { const key = keySelector(item); const value = elementSelector ? elementSelector(item) : item; if (!groups.has(key)) groups.set(key, []); groups.get(key).push(value); } const result = []; for (const [key, group] of groups.entries()) { if (resultSelector) { const groupQueryable = new InMemoryGraphQLQueryable(group); result.push(resultSelector(key, groupQueryable)); } else { result.push({ key, group }); } } return result; }); return new InMemoryGraphQLQueryable(newData); } Join(inner, outerKeySelector, innerKeySelector, resultSelector) { const newData = this.resolveData().then(async (outerItems) => { const innerItems = await inner.ToArrayAsync(); const results = []; for (const o of outerItems) { const oKey = outerKeySelector(o); for (const i of innerItems) { if (oKey === innerKeySelector(i)) { results.push(resultSelector(o, i)); } } } return results; }); return new InMemoryGraphQLQueryable(newData); } Take(count) { const newData = this.resolveData().then((items) => items.slice(0, count)); return new InMemoryGraphQLQueryable(newData); } Skip(count) { const newData = this.resolveData().then((items) => items.slice(count)); return new InMemoryGraphQLQueryable(newData); } Distinct(keySelector) { const newData = this.resolveData().then((items) => { if (keySelector) { const seen = new Set(); return items.filter((item) => { const key = keySelector(item); if (seen.has(key)) return false; seen.add(key); return true; }); } else { return Array.from(new Set(items)); } }); return new InMemoryGraphQLQueryable(newData); } Union(other) { const newData = this.resolveData().then(async (arr1) => { const arr2 = await other.ToArrayAsync(); return Array.from(new Set([...arr1, ...arr2])); }); return new InMemoryGraphQLQueryable(newData); } Intersect(other) { const newData = this.resolveData().then(async (arr1) => { const arr2 = await other.ToArrayAsync(); return arr1.filter((x) => arr2.includes(x)); }); return new InMemoryGraphQLQueryable(newData); } Except(other) { const newData = this.resolveData().then(async (arr1) => { const arr2 = await other.ToArrayAsync(); return arr1.filter((x) => !arr2.includes(x)); }); return new InMemoryGraphQLQueryable(newData); } Where = this.WhereFilter; Select = this.SelectFields; async ToArrayAsync() { return await this.resolveData(); } async ToListAsync() { const array = await this.ToArrayAsync(); return new list_1.List(array); } async FirstAsync(predicate) { const items = await this.resolveData(); if (predicate) { for (const item of items) { if (await predicate(item)) return item; } throw new Error('No matching element found'); } if (items.length === 0) { throw new Error('Sequence contains no elements'); } return items[0]; } async FirstOrDefaultAsync(predicate) { try { return await this.FirstAsync(predicate); } catch { return undefined; } } async LastAsync(predicate) { const items = await this.resolveData(); if (predicate) { for (let i = items.length - 1; i >= 0; i--) { if (await predicate(items[i])) return items[i]; } throw new Error('No matching element found'); } if (items.length === 0) { throw new Error('Sequence contains no elements'); } return items[items.length - 1]; } async LastOrDefaultAsync(predicate) { try { return await this.LastAsync(predicate); } catch { return undefined; } } async SingleAsync(predicate) { const items = await this.resolveData(); let found; let count = 0; for (const item of items) { if (!predicate || (await predicate(item))) { found = item; count++; if (count > 1) { throw new Error('Sequence contains more than one element'); } } } if (count === 0) { throw new Error('Sequence contains no elements'); } return found; } async SingleOrDefaultAsync(predicate) { try { return await this.SingleAsync(predicate); } catch (error) { if (error.message.includes('more than one element')) { throw error; } return undefined; } } async CountAsync(predicate) { const items = await this.resolveData(); if (predicate) { let count = 0; for (const item of items) { if (await predicate(item)) count++; } return count; } return items.length; } async AnyAsync(predicate) { const items = await this.resolveData(); if (predicate) { for (const item of items) { if (await predicate(item)) return true; } return false; } return items.length > 0; } async AllAsync(predicate) { const items = await this.resolveData(); for (const item of items) { if (!(await predicate(item))) return false; } return true; } async MinAsync(selector) { const items = await this.resolveData(); if (items.length === 0) { throw new Error('Sequence contains no elements'); } if (selector) { return items .map(selector) .reduce((min, current) => (current < min ? current : min)); } return items.reduce((min, current) => (current < min ? current : min)); } async MaxAsync(selector) { const items = await this.resolveData(); if (items.length === 0) { throw new Error('Sequence contains no elements'); } if (selector) { return items .map(selector) .reduce((max, current) => (current > max ? current : max)); } return items.reduce((max, current) => (current > max ? current : max)); } async SumAsync(selector) { const items = await this.resolveData(); return items .map(selector || ((x) => x)) .reduce((sum, current) => sum + current, 0); } async AverageAsync(selector) { const items = await this.resolveData(); const values = items.map(selector || ((x) => x)); return (values.reduce((sum, current) => sum + current, 0) / values.length); } async AggregateAsync(seed, func) { const items = await this.resolveData(); let accumulator = seed; for (const item of items) { accumulator = await func(accumulator, item); } return accumulator; } async ContainsAsync(item) { const items = await this.resolveData(); return items.includes(item); } async ToEnumerable() { const array = await this.ToArrayAsync(); return new enumerable_1.Enumerable(array); } async AsEnumerable() { return this.ToEnumerable(); } async AsAsyncEnumerable() { const array = await this.ToArrayAsync(); return new async_enumerable_1.AsyncEnumerable(array); } async ToEnumerableAsync() { return this.ToEnumerable(); } async ToAsyncEnumerable() { return this.AsAsyncEnumerable(); } async ExecuteAsync() { return await this.ToArrayAsync(); } async LongCountAsync(predicate) { return await this.CountAsync(predicate); } async ForEachAsync(action) { const items = await this.resolveData(); for (const item of items) { await action(item); } } async resolveData() { return Array.isArray(this.data) ? this.data : await this.data; } } exports.InMemoryGraphQLQueryable = InMemoryGraphQLQueryable; //# sourceMappingURL=graphql-queryable.js.map