import { BadRequestException, Injectable, Logger } from '@nestjs/common'; import { IConnection } from 'src/utils/pagination/interfaces/connection.interface'; import { Record as IRecord, RecordFilter, RecordOrderBy, } from 'src/tenant/query-builder/interfaces/record.interface'; import { CreateManyResolverArgs, CreateOneResolverArgs, DeleteOneResolverArgs, FindManyResolverArgs, FindOneResolverArgs, UpdateOneResolverArgs, } from 'src/tenant/query-builder/interfaces/resolvers-builder.interface'; import { QueryBuilderFactory } from 'src/tenant/query-builder/query-builder.factory'; import { parseResult } from 'src/tenant/query-runner/utils/parse-result.util'; import { TenantDataSourceService } from 'src/tenant-datasource/tenant-datasource.service'; import { QueryRunnerOptions } from './interfaces/query-runner-optionts.interface'; import { PGGraphQLMutation, PGGraphQLResult, } from './interfaces/pg-graphql.interface'; @Injectable() export class QueryRunnerService { private readonly logger = new Logger(QueryRunnerService.name); constructor( private readonly queryBuilderFactory: QueryBuilderFactory, private readonly tenantDataSourceService: TenantDataSourceService, ) {} async findMany< Record extends IRecord = IRecord, Filter extends RecordFilter = RecordFilter, OrderBy extends RecordOrderBy = RecordOrderBy, >( args: FindManyResolverArgs, options: QueryRunnerOptions, ): Promise | undefined> { const { workspaceId, targetTableName } = options; const query = this.queryBuilderFactory.findMany(args, options); const result = await this.execute(query, workspaceId); return this.parseResult>(result, targetTableName, ''); } async findOne< Record extends IRecord = IRecord, Filter extends RecordFilter = RecordFilter, >( args: FindOneResolverArgs, options: QueryRunnerOptions, ): Promise { if (!args.filter || Object.keys(args.filter).length === 0) { throw new BadRequestException('Missing filter argument'); } const { workspaceId, targetTableName } = options; const query = this.queryBuilderFactory.findOne(args, options); const result = await this.execute(query, workspaceId); const parsedResult = this.parseResult>( result, targetTableName, '', ); return parsedResult?.edges?.[0]?.node; } async createMany( args: CreateManyResolverArgs, options: QueryRunnerOptions, ): Promise { const { workspaceId, targetTableName } = options; const query = this.queryBuilderFactory.createMany(args, options); const result = await this.execute(query, workspaceId); return this.parseResult>( result, targetTableName, 'insertInto', )?.records; } async createOne( args: CreateOneResolverArgs, options: QueryRunnerOptions, ): Promise { const records = await this.createMany({ data: [args.data] }, options); return records?.[0]; } async updateOne( args: UpdateOneResolverArgs, options: QueryRunnerOptions, ): Promise { const { workspaceId, targetTableName } = options; const query = this.queryBuilderFactory.updateOne(args, options); const result = await this.execute(query, workspaceId); return this.parseResult>( result, targetTableName, 'update', )?.records?.[0]; } async deleteOne( args: DeleteOneResolverArgs, options: QueryRunnerOptions, ): Promise { const { workspaceId, targetTableName } = options; const query = this.queryBuilderFactory.deleteOne(args, options); const result = await this.execute(query, workspaceId); return this.parseResult>( result, targetTableName, 'deleteFrom', )?.records?.[0]; } private async execute( query: string, workspaceId: string, ): Promise { const workspaceDataSource = await this.tenantDataSourceService.connectToWorkspaceDataSource( workspaceId, ); await workspaceDataSource?.query(` SET search_path TO ${this.tenantDataSourceService.getSchemaName( workspaceId, )}; `); console.log('ho'); console.log(query); console.log('ha'); return workspaceDataSource?.query(` SELECT graphql.resolve($$ ${query} $$); `); } private parseResult( graphqlResult: PGGraphQLResult | undefined, targetTableName: string, command: string, ): Result { const entityKey = `${command}${targetTableName}Collection`; const result = graphqlResult?.[0]?.resolve?.data?.[entityKey]; if (!result) { throw new BadRequestException('Malformed result from GraphQL query'); } return parseResult(result); } }