diff --git a/angular.json b/angular.json index cbd743a..7dcb56c 100644 --- a/angular.json +++ b/angular.json @@ -159,6 +159,41 @@ } } } + }, + "@poweredsoft/ngx-data-apollo": { + "projectType": "library", + "root": "projects/poweredsoft/ngx-data-apollo", + "sourceRoot": "projects/poweredsoft/ngx-data-apollo/src", + "prefix": "lib", + "architect": { + "build": { + "builder": "@angular-devkit/build-ng-packagr:build", + "options": { + "tsConfig": "projects/poweredsoft/ngx-data-apollo/tsconfig.lib.json", + "project": "projects/poweredsoft/ngx-data-apollo/ng-package.json" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "projects/poweredsoft/ngx-data-apollo/src/test.ts", + "tsConfig": "projects/poweredsoft/ngx-data-apollo/tsconfig.spec.json", + "karmaConfig": "projects/poweredsoft/ngx-data-apollo/karma.conf.js" + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "projects/poweredsoft/ngx-data-apollo/tsconfig.lib.json", + "projects/poweredsoft/ngx-data-apollo/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } }}, "defaultProject": "ngx-data" } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index bfd0d35..4d862be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -418,14 +418,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -446,8 +444,7 @@ "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", @@ -598,7 +595,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -606,14 +602,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -632,7 +626,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -726,7 +719,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -812,8 +804,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -913,14 +904,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -7238,8 +7227,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -7282,8 +7270,7 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", @@ -7294,8 +7281,7 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -7412,8 +7398,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -7425,7 +7410,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -7455,7 +7439,6 @@ "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -7474,7 +7457,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -7555,8 +7537,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -7568,7 +7549,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -7654,8 +7634,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -7691,7 +7670,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7711,7 +7689,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -7755,14 +7732,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -13366,8 +13341,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -13395,7 +13369,6 @@ "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -13410,8 +13383,7 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", @@ -13422,8 +13394,7 @@ "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -13540,8 +13511,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -13553,7 +13523,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -13568,7 +13537,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -13576,14 +13544,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -13602,7 +13568,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -13683,8 +13648,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -13696,7 +13660,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -13782,8 +13745,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -13819,7 +13781,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -13839,7 +13800,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -13883,14 +13843,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, diff --git a/projects/poweredsoft/ngx-data-apollo/README.md b/projects/poweredsoft/ngx-data-apollo/README.md new file mode 100644 index 0000000..4cf56f6 --- /dev/null +++ b/projects/poweredsoft/ngx-data-apollo/README.md @@ -0,0 +1,24 @@ +# NgxDataApollo + +This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.4. + +## Code scaffolding + +Run `ng generate component component-name --project ngx-data-apollo` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ngx-data-apollo`. +> Note: Don't forget to add `--project ngx-data-apollo` or else it will be added to the default project in your `angular.json` file. + +## Build + +Run `ng build ngx-data-apollo` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Publishing + +After building your library with `ng build ngx-data-apollo`, go to the dist folder `cd dist/ngx-data-apollo` and run `npm publish`. + +## Running unit tests + +Run `ng test ngx-data-apollo` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## Further help + +To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). diff --git a/projects/poweredsoft/ngx-data-apollo/karma.conf.js b/projects/poweredsoft/ngx-data-apollo/karma.conf.js new file mode 100644 index 0000000..f308068 --- /dev/null +++ b/projects/poweredsoft/ngx-data-apollo/karma.conf.js @@ -0,0 +1,32 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join(__dirname, '../../../coverage/poweredsoft/ngx-data-apollo'), + reports: ['html', 'lcovonly', 'text-summary'], + fixWebpackSourcePaths: true + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false, + restartOnFileChange: true + }); +}; diff --git a/projects/poweredsoft/ngx-data-apollo/ng-package.json b/projects/poweredsoft/ngx-data-apollo/ng-package.json new file mode 100644 index 0000000..239d185 --- /dev/null +++ b/projects/poweredsoft/ngx-data-apollo/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../../dist/poweredsoft/ngx-data-apollo", + "lib": { + "entryFile": "src/public-api.ts" + } +} \ No newline at end of file diff --git a/projects/poweredsoft/ngx-data-apollo/package.json b/projects/poweredsoft/ngx-data-apollo/package.json new file mode 100644 index 0000000..1b6b177 --- /dev/null +++ b/projects/poweredsoft/ngx-data-apollo/package.json @@ -0,0 +1,15 @@ +{ + "name": "@poweredsoft/ngx-data-apollo", + "version": "0.0.1", + "peerDependencies": { + "@poweredsoft/data": "^0.0.26", + "@angular/common": "^8.2.4", + "@angular/core": "^8.2.4", + "apollo-angular-link-http": "^1.9.0", + "apollo-link": "^1.2.11", + "apollo-client": "^2.6.0", + "apollo-cache-inmemory": "^1.6.0", + "graphql-tag": "^2.10.0", + "graphql": "^14.5.0" + } +} \ No newline at end of file diff --git a/projects/poweredsoft/ngx-data-apollo/src/lib/GraphQLDataSourceOptionsBuilder.ts b/projects/poweredsoft/ngx-data-apollo/src/lib/GraphQLDataSourceOptionsBuilder.ts new file mode 100644 index 0000000..0a2a6c9 --- /dev/null +++ b/projects/poweredsoft/ngx-data-apollo/src/lib/GraphQLDataSourceOptionsBuilder.ts @@ -0,0 +1,274 @@ +import { IDataSourceOptions, IQueryCriteria, IDataSourceTransportOptions, IDataSourceQueryAdapterOptions, IDataSourceCommandAdapterOptions, IAdvanceQueryAdapter, IFilter, IAggregate, ISort, IGroup, ISimpleFilter, ICompositeFilter, IQueryExecutionGroupResult, IQueryExecutionResult, IAggregateResult } from '@poweredsoft/data'; +import { Apollo } from 'apollo-angular'; +import { IGraphQLAdvanceQueryResult, IGraphQLAdvanceQueryInput, IGraphQLAdvanceQueryFilterInput, IGraphQLAdvanceQueryAggregateInput, IGraphQLAdvanceQuerySortInput, IGraphQLAdvanceQueryGroupInput, FilterType, IGraphQLAdvanceQueryAggregateResult, IGraphQLVariantResult, AggregateType } from './models'; +import gql from 'graphql-tag'; +import { DocumentNode } from 'graphql'; +import { map, catchError } from 'rxjs/operators'; +import { Observable } from 'rxjs'; + +export class GraphQLDataSourceOptionsBuilder { + + private _commands: { [key: string] : IDataSourceCommandAdapterOptions }; + + constructor(private apollo: Apollo, + private queryName: string, + private queryInputName: string, + private querySelect: string, + private keyResolver: (model: TModel) => TKey, + private defaultCriteria: IQueryCriteria, + private manageNotificationMessage: boolean) + { + } + create(): IDataSourceOptions { + let ret: IDataSourceOptions = { + resolveIdField: this.keyResolver, + defaultCriteria: this.defaultCriteria, + manageNotificationMessage: this.manageNotificationMessage, + transport: this.createTransport() + }; + return ret; + } + protected createTransport(): IDataSourceTransportOptions { + let ret: IDataSourceTransportOptions = { + query: this.createQuery(), + commands: this._commands + }; + return ret; + } + + 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 + } + }); + return o$.pipe( + map(result => { + const queryResult = result.data[this.queryName] as IGraphQLAdvanceQueryResult; + return this.queryResultFromGraphQLAdvancedResult(query, queryResult); + }), + catchError(err => { + console.error(err); + return err; + }) + ); + } + } + }; + return ret; + } + private queryResultFromGraphQLAdvancedResult(query: IQueryCriteria, result: IGraphQLAdvanceQueryResult): IQueryExecutionResult | IQueryExecutionGroupResult { + if (query.groups && query.groups.length) { + throw 'todo'; + } + const ret: IQueryExecutionResult = { + data: result.data, + totalRecords: result.totalRecords, + numberOfPages: result.numberOfPages, + aggregates: result.aggregates ? result.aggregates.map(this.fromGraphQLAggregateResult.bind(this)) : null + }; + return ret; + } + private fromGraphQLAggregateResult(agg: IGraphQLAdvanceQueryAggregateResult): IAggregateResult { + return { + path: agg.path, + type: this.normalizeFirstLetter(agg.type), + value: this.getValueFromVariantResult(agg.value) + }; + } + + private normalizeFirstLetter(type: string): string { + if (type) { + const ret = type.toLowerCase(); + return ret.substring(0, 1).toUpperCase() + ret.substring(1); + } + + return type; + } + + private getValueFromVariantResult(variant: IGraphQLVariantResult): any { + + if (variant && variant.typeName) + { + if (variant.typeName.toLowerCase() == "int") + return variant.intValue; + else if (variant.typeName.toLowerCase() == "long") + return variant.longValue; + else if (variant.typeName.toLowerCase() == "boolean") + return variant.booleanValue; + else if (variant.typeName.toLowerCase() == "decimal") + return variant.decimalValue; + else if (variant.typeName.toLowerCase() == "datetime") + return variant.dateTimeValue; + else if (variant.typeName.toLowerCase() == "string") + return variant.stringValue; + else if (variant.typeName.toLowerCase() == "json") + return JSON.parse(variant.json); + } + + return null; + } + private createGraphQLQuery(query: IQueryCriteria): DocumentNode { + return gql` + query getAll($criteria: ${this.queryInputName}) { + ${this.queryName}(params: $criteria) { + totalRecords + numberOfPages + ${this.createAggregateSelect(query)} + ${this.createQuerySelect(query)} + } + } + `; + } + + private createAggregateSelect(query: IQueryCriteria): any { + + if (query.aggregates && query.aggregates.length) + { + return ` + aggregates { + type + path + value { + booleanValue + dateTimeValue + decimalValue + intValue + json + longValue + stringValue + typeName + } + } + `; + } + + return ''; + } + + private createGraphQLQueryCriteria(query: IQueryCriteria): IGraphQLAdvanceQueryInput { + const ret: IGraphQLAdvanceQueryInput = { + page: query.page, + pageSize: query.pageSize, + filters: query.filters ? query.filters.map(this.convertFilter.bind(this)) : null, + sorts: query.sorts ? query.sorts.map(this.convertSort.bind(this)) : null, + aggregates: query.aggregates ? query.aggregates.map(this.convertAggregates.bind(this)) : null, + groups: query.groups ? query.groups.map(this.convertGroup.bind(this)) : null + }; + return ret; + } + + public addMutation(name: string, handle: (command: TMutation) => Observable) { + + this._commands[name] = > { + adapter: { + handle: handle + } + }; + + return this; + } + + private createQuerySelect(query: IQueryCriteria): string { + if (query.groups && query.groups.length) { + throw 'todo'; + } + return ` + data { + ${this.querySelect} + } + `; + } + private convertGroup(group: IGroup): IGraphQLAdvanceQueryGroupInput { + return { + path: group.path, + ascending: group.ascending + }; + } + private convertAggregates(aggregate: IAggregate): IGraphQLAdvanceQueryAggregateInput { + return { + path: aggregate.path, + type: this.resolveAggregateType(aggregate.type) + }; + } + + private resolveAggregateType(type: string): AggregateType { + + return type ? type.toUpperCase() as any : null; + + /* + + if (type) + { + if (type.toUpperCase() == 'COUNT') return AggregateType.COUNT + if (type.toUpperCase() == 'SUM') return AggregateType.SUM + if (type.toUpperCase() == 'AVG') return AggregateType.AVG + if (type.toUpperCase() == 'LONGCOUNT') return AggregateType.LONGCOUNT + if (type.toUpperCase() == 'MIN') return AggregateType.MIN + if (type.toUpperCase() == 'MAX') return AggregateType.MAX + if (type.toUpperCase() == 'FIRST') return AggregateType.FIRST + if (type.toUpperCase() == 'FIRSTORDEFAULT') return AggregateType.FIRSTORDEFAULT + if (type.toUpperCase() == 'LAST') return AggregateType.LAST + if (type.toUpperCase() == 'LASTORDEFAULT') return AggregateType.LASTORDEFAULT + } + + throw new Error('Aggregate type');*/ + } + + private convertSort(sort: ISort): IGraphQLAdvanceQuerySortInput { + return { + path: sort.path, + ascending: sort.ascending + }; + } + private convertFilter(filter: IFilter): IGraphQLAdvanceQueryFilterInput { + if (filter.type == "Composite") { + const compositeFilter = filter as ICompositeFilter; + return { + not: false, + and: compositeFilter.and, + type: FilterType.COMPOSITE, + filters: compositeFilter.filters.map(this.convertFilter.bind(this)), + }; + } + const simpleFilter = filter as ISimpleFilter; + return { + filters: null, + and: filter.and, + not: false, + path: simpleFilter.path, + type: this.resolveFilterType(simpleFilter.type), + value: { + stringValue: simpleFilter.value as string + } + }; + } + + private resolveFilterType(type: string): FilterType { + return type ? type.toUpperCase() as any: null; + + /* + if (type) + { + if (type.toUpperCase() == 'EQUAL') return FilterType.EQUAL + if (type.toUpperCase() == 'CONTAINS') return FilterType.CONTAINS + if (type.toUpperCase() == 'STARTSWITH') return FilterType.STARTSWITH + if (type.toUpperCase() == 'ENDSWITH') return FilterType.ENDSWITH + if (type.toUpperCase() == 'COMPOSITE') return FilterType.COMPOSITE + if (type.toUpperCase() == 'NOTEQUAL') return FilterType.NOTEQUAL + if (type.toUpperCase() == 'GREATERTHAN') return FilterType.GREATERTHAN + if (type.toUpperCase() == 'LESSTHANOREQUAL') return FilterType.LESSTHANOREQUAL + if (type.toUpperCase() == 'GREATERTHANOREQUAL') return FilterType.GREATERTHANOREQUAL + if (type.toUpperCase() == 'LESSTHAN') return FilterType.LESSTHAN + if (type.toUpperCase() == 'IN') return FilterType.IN + if (type.toUpperCase() == 'NOTIN') return FilterType.NOTIN + } + + throw new Error('unknown filter type');*/ + } +} diff --git a/projects/poweredsoft/ngx-data-apollo/src/lib/graphql-datas-source.service.ts b/projects/poweredsoft/ngx-data-apollo/src/lib/graphql-datas-source.service.ts new file mode 100644 index 0000000..a41d727 --- /dev/null +++ b/projects/poweredsoft/ngx-data-apollo/src/lib/graphql-datas-source.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@angular/core'; +import { IQueryCriteria, IDataSource } from '@poweredsoft/data'; +import { Apollo } from 'apollo-angular'; +import { GraphQLDataSourceOptionsBuilder } from './GraphQLDataSourceOptionsBuilder'; + +@Injectable({ + providedIn: 'root' +}) +export class GraphQLDataSourceService +{ + constructor(private apollo: Apollo) { + + } + + createDataSourceOptionsBuilder( + queryName: string, + queryInputName: string, + querySelect: string, + keyResolver: (model: TModel) => TKey, + defaultCriteria: IQueryCriteria, + manageNotificationMessage: boolean = true) : GraphQLDataSourceOptionsBuilder + { + return new GraphQLDataSourceOptionsBuilder( + this.apollo, + queryName, + queryInputName, + querySelect, + keyResolver, + defaultCriteria, + manageNotificationMessage + ); + } +} + diff --git a/projects/poweredsoft/ngx-data-apollo/src/lib/models.ts b/projects/poweredsoft/ngx-data-apollo/src/lib/models.ts new file mode 100644 index 0000000..c2f19e5 --- /dev/null +++ b/projects/poweredsoft/ngx-data-apollo/src/lib/models.ts @@ -0,0 +1,94 @@ +export enum AggregateType { + COUNT, + SUM, + AVG, + LONGCOUNT, + MIN, + MAX, + FIRST, + FIRSTORDEFAULT, + LAST, + LASTORDEFAULT +} + +export enum FilterType { + EQUAL, + CONTAINS, + STARTSWITH, + ENDSWITH, + COMPOSITE, + NOTEQUAL, + GREATERTHAN, + LESSTHANOREQUAL, + GREATERTHANOREQUAL, + LESSTHAN, + IN, + NOTIN +} + +export interface IGraphQLVariantInput { + dateTimeValue?: Date + decimalValue?: number + intValue?: number + longValue?: number + stringValue?: string + booleanValue?: boolean; +} + +export interface IGraphQLVariantResult { + dateTimeValue?: string; + decimalValue?: number; + intValue?: number; + json?: string; + longValue?: number; + stringValue?: string; + booleanValue?: boolean; + typeName: string; +} + +export interface IGraphQLAdvanceQueryAggregateInput { + path?: string; + type: AggregateType; +} + +export interface IGraphQLAdvanceQueryAggregateResult { + path: string + type: string + value: IGraphQLVariantResult +} + +export interface IGraphQLAdvanceQueryFilterInput { + and?: boolean + filters?: IGraphQLAdvanceQueryFilterInput[] + not?: boolean + path?: string + type: FilterType + value?: IGraphQLVariantInput +} + +export interface IGraphQLAdvanceQueryGroupInput { + ascending?: boolean + path: string +} + +export interface IGraphQLAdvanceQuerySortInput { + ascending?: boolean + path: string +} + +export interface IGraphQLAdvanceQueryInput { + aggregates?: IGraphQLAdvanceQueryAggregateInput[] + filters?: IGraphQLAdvanceQueryFilterInput[] + groups?: IGraphQLAdvanceQueryGroupInput[] + page?: number + pageSize?: number + sorts?: IGraphQLAdvanceQuerySortInput[] +} + +export interface IGraphQLAdvanceQueryResult { + aggregates?: IGraphQLAdvanceQueryAggregateResult[]; + data?: T[]; + groups?: IGraphQLAdvanceQueryResult[]; + numberOfPages?: number; + totalRecords: number; +} \ No newline at end of file diff --git a/projects/poweredsoft/ngx-data-apollo/src/public-api.ts b/projects/poweredsoft/ngx-data-apollo/src/public-api.ts new file mode 100644 index 0000000..2e1ae8e --- /dev/null +++ b/projects/poweredsoft/ngx-data-apollo/src/public-api.ts @@ -0,0 +1,9 @@ +import { GraphQLDataSourceService } from "./lib/graphql-datas-source.service"; + +/* + * Public API Surface of ngx-data-apollo + */ + +export * from './lib/graphql-datas-source.service'; +export * from './lib/GraphQLDataSourceOptionsBuilder'; +export * from './lib/models'; \ No newline at end of file diff --git a/projects/poweredsoft/ngx-data-apollo/tsconfig.lib.json b/projects/poweredsoft/ngx-data-apollo/tsconfig.lib.json new file mode 100644 index 0000000..7f2be06 --- /dev/null +++ b/projects/poweredsoft/ngx-data-apollo/tsconfig.lib.json @@ -0,0 +1,26 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../../../out-tsc/lib", + "target": "es2015", + "declaration": true, + "inlineSources": true, + "types": [], + "lib": [ + "dom", + "es2018" + ] + }, + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "fullTemplateTypeCheck": true, + "strictInjectionParameters": true, + "enableResourceInlining": true + }, + "exclude": [ + "src/test.ts", + "**/*.spec.ts" + ] +} diff --git a/projects/poweredsoft/ngx-data-apollo/tsconfig.spec.json b/projects/poweredsoft/ngx-data-apollo/tsconfig.spec.json new file mode 100644 index 0000000..4acf941 --- /dev/null +++ b/projects/poweredsoft/ngx-data-apollo/tsconfig.spec.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../../../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "src/test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/projects/poweredsoft/ngx-data-apollo/tslint.json b/projects/poweredsoft/ngx-data-apollo/tslint.json new file mode 100644 index 0000000..3aa2f4c --- /dev/null +++ b/projects/poweredsoft/ngx-data-apollo/tslint.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "lib", + "camelCase" + ], + "component-selector": [ + true, + "element", + "lib", + "kebab-case" + ] + } +} diff --git a/projects/poweredsoft/ngx-data/package.json b/projects/poweredsoft/ngx-data/package.json index 6355451..3626e3f 100644 --- a/projects/poweredsoft/ngx-data/package.json +++ b/projects/poweredsoft/ngx-data/package.json @@ -5,12 +5,6 @@ "@angular/common": "^8.2.4", "@angular/core": "^8.2.4", "@poweredsoft/data": "^0.0.26", - "rxjs": "^6.5.3", - "apollo-angular-link-http": "^1.9.0", - "apollo-link": "^1.2.11", - "apollo-client": "^2.6.0", - "apollo-cache-inmemory": "^1.6.0", - "graphql-tag": "^2.10.0", - "graphql": "^14.5.0" + "rxjs": "^6.5.3" } } \ No newline at end of file diff --git a/src/app/app.component.html b/src/app/app.component.html index 654b02f..392f50d 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -4,4 +4,8 @@ + + \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 0137c81..dd119b2 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -2,6 +2,14 @@ import { Component, OnInit } from '@angular/core'; import { GenericRestDataSourceService } from 'projects/poweredsoft/ngx-data/src/public-api'; import { of } from 'rxjs'; import { DataSource } from '@poweredsoft/data'; +import { GraphQLDataSourceService } from 'projects/poweredsoft/ngx-data-apollo/src/public-api'; + + +export interface IContact { + id: number; + firstName :string; + lastName: string; +} export interface ICustomerModel { id: number; @@ -18,7 +26,7 @@ export class AppComponent implements OnInit { title = 'ngx-data'; dataSource: DataSource; - constructor(genericService: GenericRestDataSourceService) { + constructor(genericService: GenericRestDataSourceService, private graphQLService: GraphQLDataSourceService) { const keyResolver = (model: ICustomerModel) => model.id; const transportOptions = genericService.createStandardRestTransportOptions('api/customer', keyResolver); @@ -68,4 +76,29 @@ export class AppComponent implements OnInit { //console.log(error); }); } + + testGraphQL() { + const builder = this.graphQLService.createDataSourceOptionsBuilder( + 'contacts', + 'GraphQLAdvanceQueryOfContactModelInput', + 'id firstName lastName', + (m) => m.id, + { + aggregates: [ + { + path: 'id', + type: 'Max' + } + ] + } + ); + + const dataSourceOptions = builder.create(); + const dataSource = new DataSource(dataSourceOptions); + + const subscription = dataSource.data$.subscribe(contacts => { + console.log(contacts); + }); + dataSource.refresh(); + } } diff --git a/src/app/graphql.module.ts b/src/app/graphql.module.ts index e387728..7cd8b75 100644 --- a/src/app/graphql.module.ts +++ b/src/app/graphql.module.ts @@ -3,7 +3,7 @@ import {ApolloModule, APOLLO_OPTIONS} from 'apollo-angular'; import {HttpLinkModule, HttpLink} from 'apollo-angular-link-http'; import {InMemoryCache} from 'apollo-cache-inmemory'; -const uri = ''; // <-- add the URL of the GraphQL server here +const uri = 'https://localhost:5001/graphql'; // <-- add the URL of the GraphQL server here export function createApollo(httpLink: HttpLink) { return { link: httpLink.create({uri}), diff --git a/tsconfig.json b/tsconfig.json index 2ab2dbd..711b249 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,6 +25,12 @@ ], "@poweredsoft/ngx-data/*": [ "dist/poweredsoft/ngx-data/*" + ], + "@poweredsoft/ngx-data-apollo": [ + "dist/poweredsoft/ngx-data-apollo" + ], + "@poweredsoft/ngx-data-apollo/*": [ + "dist/poweredsoft/ngx-data-apollo/*" ] } },