diff --git a/projects/poweredsoft/ngx-data-apollo/src/lib/GraphQLDataSourceOptionsBuilder.ts b/projects/poweredsoft/ngx-data-apollo/src/lib/GraphQLDataSourceOptionsBuilder.ts index d9870da..62216d2 100644 --- a/projects/poweredsoft/ngx-data-apollo/src/lib/GraphQLDataSourceOptionsBuilder.ts +++ b/projects/poweredsoft/ngx-data-apollo/src/lib/GraphQLDataSourceOptionsBuilder.ts @@ -4,14 +4,17 @@ import { IGraphQLAdvanceQueryResult, IGraphQLAdvanceQueryInput, IGraphQLAdvanceQ import gql from 'graphql-tag'; import { DocumentNode, GraphQLError } from 'graphql'; import { map, catchError, switchMap } from 'rxjs/operators'; -import { Observable, throwError } from 'rxjs'; +import { Observable, throwError, of } from 'rxjs'; import { FetchResult } from 'apollo-link'; -import { of } from 'zen-observable'; import { ApolloError } from 'apollo-client'; + export class GraphQLDataSourceOptionsBuilder { + + private _commands: { [key: string] : IDataSourceCommandAdapterOptions }; + private _beforeRead: (TQuery: IGraphQLAdvanceQueryInput) => Observable>; + querySelect: string; - private _commands: { [key: string] : IDataSourceCommandAdapterOptions } = {}; constructor(private apollo: Apollo, private queryName: string, @@ -44,33 +47,45 @@ export class GraphQLDataSourceOptionsBuilder { }; return ret; } + + public beforeRead>(beforeRead: (query: TAdvanceQuery) => Observable) + { + this._beforeRead = beforeRead; + return this._beforeRead; + } protected createQuery(): IDataSourceQueryAdapterOptions { let ret: IDataSourceQueryAdapterOptions = { adapter: >{ handle: (query: IQueryCriteria) => { - - const advanceQuery = this.createGraphQLQueryCriteria(query); - const o$ = this.apollo.query({ - query: this.createGraphQLQuery(query), - variables: { - criteria: advanceQuery - }, - fetchPolicy: 'no-cache' - }); - - return o$.pipe( - map(result => { - const queryResult = result.data[this.queryName] as IGraphQLAdvanceQueryResult; - return this.queryResultFromGraphQLAdvancedResult(query, queryResult); - }) - ); + + const finalBeforeRead = this._beforeRead || (t => of(t)); + const advanceQuery = this.createGraphQLQueryCriteria(query); + return finalBeforeRead(advanceQuery) + .pipe( + switchMap(finalAdvanceQuery => { + const o$ = this.apollo.query({ + query: this.createGraphQLQuery(finalAdvanceQuery), + variables: { + criteria: finalAdvanceQuery + } + }); + + return o$.pipe( + map(result => { + const queryResult = result.data[this.queryName] as IGraphQLAdvanceQueryResult; + return this.queryResultFromGraphQLAdvancedResult(finalAdvanceQuery, queryResult); + }) + ); + }) + ); } } }; return ret; } - private queryResultFromGraphQLAdvancedResult(query: IQueryCriteria, result: IGraphQLAdvanceQueryResult): IQueryExecutionResult | IQueryExecutionGroupResult { + + private queryResultFromGraphQLAdvancedResult(query: IGraphQLAdvanceQueryInput, result: IGraphQLAdvanceQueryResult): IQueryExecutionResult | IQueryExecutionGroupResult { const ret: IQueryExecutionGroupResult & IQueryExecutionResult = { data: result.data, @@ -132,8 +147,8 @@ export class GraphQLDataSourceOptionsBuilder { return null; } - - private createGraphQLQuery(query: IQueryCriteria): DocumentNode { + + private createGraphQLQuery(query: IGraphQLAdvanceQueryInput): DocumentNode { return gql` query getAll($criteria: ${this.queryInputName}) { ${this.queryName}(params: $criteria) { @@ -146,7 +161,7 @@ export class GraphQLDataSourceOptionsBuilder { `; } - private createAggregateSelect(query: IQueryCriteria): any { + private createAggregateSelect(query: IGraphQLAdvanceQueryInput): any { if (query.aggregates && query.aggregates.length) { @@ -236,7 +251,7 @@ export class GraphQLDataSourceOptionsBuilder { return this; } - private createGroupSelect(query: IQueryCriteria, group: IGroup, isLast: boolean) { + private createGroupSelect(query: IGraphQLAdvanceQueryInput, group: IGroup, isLast: boolean) { let ret = ` groupPath groupValue { @@ -267,7 +282,7 @@ export class GraphQLDataSourceOptionsBuilder { return `booleanValue dateTimeValue decimalValue intValue json longValue stringValue typeName`; } - private createQuerySelect(query: IQueryCriteria): string { + private createQuerySelect(query: IGraphQLAdvanceQueryInput): string { if (query.groups && query.groups.length) { const groupSelect = query.groups.reduce((prev, current, currentIndex) => { diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 7d16c49..a7b4c20 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -2,11 +2,12 @@ import { Component, OnInit } from '@angular/core'; import { GenericRestDataSourceService } from 'projects/poweredsoft/ngx-data/src/public-api'; import { of, Observable } from 'rxjs'; import { DataSource, IResolveCommandModelEvent } from '@poweredsoft/data'; -import { GraphQLDataSourceService } from 'projects/poweredsoft/ngx-data-apollo/src/public-api'; +import { } from 'projects/poweredsoft/ngx-data-apollo/src/public-api'; import { Apollo } from 'apollo-angular'; import gql from 'graphql-tag'; import { map } from 'rxjs/operators'; import { DocumentNode } from 'graphql'; +import { GraphQLDataSourceService, IGraphQLAdvanceQueryInput } from 'projects/poweredsoft/ngx-data-apollo/src/public-api'; export interface IContact { @@ -15,7 +16,7 @@ export interface IContact { lastName: string; } -export interface ICustomerModel { +export interface IContactModel { id: number; firstName: string; lastName: string; @@ -26,6 +27,11 @@ export interface IFooCommand { comment: string; } +export interface IContactDetailQuery extends IGraphQLAdvanceQueryInput +{ + sex?: string; +} + @Component({ selector: 'app-root', templateUrl: './app.component.html', @@ -33,14 +39,14 @@ export interface IFooCommand { }) export class AppComponent implements OnInit { title = 'ngx-data'; - dataSource: DataSource; + dataSource: DataSource; constructor(genericService: GenericRestDataSourceService, private apollo: Apollo, private graphQLService: GraphQLDataSourceService) { - const keyResolver = (model: ICustomerModel) => model.id; + const keyResolver = (model: IContactModel) => model.id; const transportOptions = genericService.createStandardRestTransportOptions('api/customer', keyResolver); - this.dataSource = new DataSource({ + this.dataSource = new DataSource({ resolveIdField: keyResolver, transport: transportOptions, defaultCriteria: { @@ -151,17 +157,13 @@ export class AppComponent implements OnInit { } testGraphQL() { + const builder = this.graphQLService.createDataSourceOptionsBuilder( 'contacts', - 'GraphQLAdvanceQueryOfContactModelInput', + 'ContactDetailQueryInput', 'id firstName lastName', (m) => m.id, { - groups: [ - { - path: 'sex' - } - ], aggregates: [ { path: 'id', @@ -171,6 +173,10 @@ export class AppComponent implements OnInit { } ); + builder.beforeRead(query => { + return of({ ...query, sex: "Male"}); + }); + const dataSourceOptions = builder.create(); const dataSource = new DataSource(dataSourceOptions); diff --git a/src/app/graphql.module.ts b/src/app/graphql.module.ts index c3f8cb9..a65eee2 100644 --- a/src/app/graphql.module.ts +++ b/src/app/graphql.module.ts @@ -1,24 +1,26 @@ import {NgModule} from '@angular/core'; -import {ApolloModule, APOLLO_OPTIONS} from 'apollo-angular'; +import {ApolloModule, APOLLO_OPTIONS, Apollo} from 'apollo-angular'; import {HttpLinkModule, HttpLink} from 'apollo-angular-link-http'; import {InMemoryCache} from 'apollo-cache-inmemory'; -const uri = 'http://localhost:5000/graphql'; // <-- add the URL of the GraphQL server here -export function createApollo(httpLink: HttpLink) { - return { - link: httpLink.create({uri}), - cache: new InMemoryCache(), - }; -} - @NgModule({ - exports: [ApolloModule, HttpLinkModule], - providers: [ - { - provide: APOLLO_OPTIONS, - useFactory: createApollo, - deps: [HttpLink], - }, - ], + exports: [ApolloModule, HttpLinkModule] }) -export class GraphQLModule {} +export class GraphQLModule { + constructor(apollo: Apollo, + httpLink: HttpLink) + { + const cache = new InMemoryCache(); + + const endpoint = "https://localhost:5001/graphql"; + apollo.create({ + link: httpLink.create({uri: endpoint}), + cache, + defaultOptions: { + query: { + fetchPolicy: 'network-only' + } + } + }); + } +}