UNPKG

@eleven-am/nestjs-graphql-crud

Version:

nestjs-graphql-crud is a library that aims to reduce the boilerplate code needed to create a GraphQL CRUD API.

234 lines 11 kB
"use strict"; /** * @module createBaseCrudService * @description Creates a service class that implements CRUD operations using a data provider */ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createBaseCrudService = createBaseCrudService; const common_1 = require("@nestjs/common"); const internalTypes_1 = require("./internalTypes"); const decorators_1 = require("./decorators"); const graphql_subscriptions_1 = require("graphql-subscriptions"); const core_1 = require("@nestjs/core"); /** * Creates a service class with standard CRUD operations for a specific model * * @template Item - The entity type this service will manage * @template CreateInput - The input type for create operations * @template UpdateInput - The input type for update operations * @template UpdateManyInput - The input type for update many operations * @template WhereInput - The input type for query filters * @template Target - The related entity type for one-to-many relations * @template TargetWhereInput - The input type for query filters for the related entity * @template TResolver - The type of the resolver class * * @param {string} modelName - The name of the model * @param {symbol} dataProviderToken - Symbol for the data provider token * @param {symbol} fieldSelectionToken - Symbol for the field selection provider token * @returns {Type} A dynamically generated service class with CRUD operations */ function createBaseCrudService(modelName, dataProviderToken, fieldSelectionToken) { let BaseCrudService = class BaseCrudService { constructor(moduleRef, pubSub, dataProvider, fieldSelectionProvider) { this.moduleRef = moduleRef; this.pubSub = pubSub; this.dataProvider = dataProvider; this.fieldSelectionProvider = fieldSelectionProvider; } /** * Create a new entity * * @param {CreateInput} data - The data to create the entity with * @param {any} select - Fields to select in the result * @returns {Promise<Item>} The newly created entity */ async create(data, select) { const res = await this.dataProvider.create(modelName, data, select); await this.publish(internalTypes_1.CrudAction.CREATE, res); return res; } /** * Delete an entity by ID * * @param {any} ability - The user's ability for authorization * @param {string} whereId - The ID of the entity to delete * @param {any} select - Fields to select in the result * @returns {Promise<Item>} The deleted entity */ async delete(ability, whereId, select) { const res = await this.dataProvider.delete(modelName, ability, whereId, select); await this.publish(internalTypes_1.CrudAction.DELETE, res); return res; } /** * Delete multiple entities matching criteria * * @param {any} ability - The user's ability for authorization * @param {WhereInput} where - Filter criteria for entities to delete * @param {any} select - Fields to select in the result * @returns {Promise<Item[]>} Array of deleted entities */ async deleteMany(ability, where, select) { const gotDeleted = await this.dataProvider.findMany(modelName, ability, { where }, select); await this.dataProvider.deleteMany(modelName, ability, where, select); await this.publish(internalTypes_1.CrudAction.DELETE_MANY, gotDeleted); return gotDeleted; } /** * Find multiple entities matching criteria * Now supports both custom FindManyArgs and default FindManyContract * * @param {any} ability - The user's ability for authorization * @param {any} args - Filter and pagination criteria (can be custom or default format) * @param {any} select - Fields to select in the result * @returns {Promise<Item[]>} Array of matched entities */ async findMany(ability, args, select) { // Normalize args to handle both custom FindManyArgs and default FindManyContract let normalizedArgs; if (args.where !== undefined || args.pagination !== undefined) { // Default FindManyContract format { where?: WhereInput, pagination?: PaginationContract } normalizedArgs = { where: args.where || {}, pagination: args.pagination, orderBy: undefined // Default doesn't support orderBy }; } else { // Custom FindManyArgs format (like prisma-nest-graphql generates) // Extract fields directly from the args object normalizedArgs = { where: args.where || {}, pagination: { take: args.take, skip: args.skip }, orderBy: args.orderBy, cursor: args.cursor, distinct: args.distinct }; } return this.dataProvider.findMany(modelName, ability, normalizedArgs, select); } /** * Find a single entity by criteria * * @param {any} ability - The user's ability for authorization * @param {WhereInput} where - Filter criteria * @param {any} select - Fields to select in the result * @returns {Promise<Item | null>} The found entity or null */ async findOne(ability, where, select) { return this.dataProvider.findOne(modelName, ability, where, select); } /** * Update a single entity by ID * * @param {any} ability - The user's ability for authorization * @param {UpdateInput} data - The data to update * @param {string} whereId - The ID of the entity to update * @param {any} select - Fields to select in the result * @returns {Promise<Item>} The updated entity */ async update(ability, data, whereId, select) { const res = await this.dataProvider.update(modelName, ability, data, whereId, select); await this.publish(internalTypes_1.CrudAction.UPDATE, res); return res; } /** * Update multiple entities matching criteria * * @param {any} ability - The user's ability for authorization * @param {UpdateManyInput} data - The data to update * @param {WhereInput} where - Filter criteria for entities to update * @param {any} select - Fields to select in the result * @returns {Promise<Item[]>} Array of updated entities */ async updateMany(ability, data, where, select) { const gotUpdated = await this.dataProvider.findMany(modelName, ability, { where }, select); await this.dataProvider.updateMany(modelName, ability, data, where, select); await this.publish(internalTypes_1.CrudAction.UPDATE_MANY, gotUpdated); return gotUpdated; } /** * Resolve a one-to-one relation * * @param {any} ability - The user's ability for authorization * @param {string} targetModel - The name of the target model * @param {string} itemId - The ID of the related item * @param {any} select - Fields to select in the result * @returns {Promise<unknown>} The related entity or null */ resolveOneToOne(ability, targetModel, itemId, select) { return this.dataProvider.findOne(targetModel, ability, { id: itemId }, select); } /** * Resolve a one-to-many relation * * @param {any} ability - The user's ability for authorization * @param {string} targetModel - The name of the target model * @param {string} foreignKey - The foreign key field name * @param {string} itemId - The ID of the related item * @param {any} select - Fields to select in the result * @param {any} [where] - Optional filter criteria for the related entities */ resolveOneToMany(ability, targetModel, foreignKey, itemId, select, where) { return this.dataProvider.findMany(targetModel, ability, { where: { ...(where?.where || {}), [foreignKey]: itemId }, pagination: where?.pagination }, select); } /** * Get the factory for a specific resolver * * @param {Type<TResolver>} constructor - The constructor of the resolver */ getFactory(constructor) { return this.moduleRef.get(constructor, { strict: false }); } /** * Publish changes to subscribers * * @private * @param {CrudAction} action - The type of action that occurred * @param {any} data - The data to publish * @returns {Promise<void>} */ async publish(action, data) { const arrayData = Array.isArray(data) ? data : [data]; await this.pubSub.publish(modelName, { action, data: arrayData, }); } }; BaseCrudService = __decorate([ (0, common_1.Injectable)(), __param(1, (0, decorators_1.CurrentPubSub)()), __param(2, (0, common_1.Inject)(dataProviderToken)), __param(3, (0, common_1.Inject)(fieldSelectionToken)), __metadata("design:paramtypes", [core_1.ModuleRef, graphql_subscriptions_1.PubSub, Object, Object]) ], BaseCrudService); Object.defineProperty(BaseCrudService, 'name', { value: `${(0, decorators_1.firstLetterUppercase)(modelName)}Service`, writable: false, }); return BaseCrudService; } //# sourceMappingURL=createBaseCrudService.js.map