completly refactor project
This commit is contained in:
		
							parent
							
								
									5d4c94c81a
								
							
						
					
					
						commit
						c18201dcd2
					
				| @ -8,6 +8,9 @@ indent_size = 2 | ||||
| insert_final_newline = true | ||||
| trim_trailing_whitespace = true | ||||
| 
 | ||||
| [*.ts] | ||||
| quote_type = single | ||||
| 
 | ||||
| [*.md] | ||||
| max_line_length = off | ||||
| trim_trailing_whitespace = false | ||||
|  | ||||
							
								
								
									
										26
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,21 +1,18 @@ | ||||
| # See http://help.github.com/ignore-files/ for more about ignoring files. | ||||
| # See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. | ||||
| 
 | ||||
| # compiled output | ||||
| # Compiled output | ||||
| /dist | ||||
| /tmp | ||||
| /out-tsc | ||||
| # Only exists if Bazel was run | ||||
| /bazel-out | ||||
| 
 | ||||
| # dependencies | ||||
| # Node | ||||
| /node_modules | ||||
| 
 | ||||
| # profiling files | ||||
| chrome-profiler-events*.json | ||||
| speed-measure-plugin*.json | ||||
| npm-debug.log | ||||
| yarn-error.log | ||||
| 
 | ||||
| # IDEs and editors | ||||
| /.idea | ||||
| .idea/ | ||||
| .project | ||||
| .classpath | ||||
| .c9/ | ||||
| @ -23,7 +20,7 @@ speed-measure-plugin*.json | ||||
| .settings/ | ||||
| *.sublime-workspace | ||||
| 
 | ||||
| # IDE - VSCode | ||||
| # Visual Studio Code | ||||
| .vscode/* | ||||
| !.vscode/settings.json | ||||
| !.vscode/tasks.json | ||||
| @ -31,16 +28,15 @@ speed-measure-plugin*.json | ||||
| !.vscode/extensions.json | ||||
| .history/* | ||||
| 
 | ||||
| # misc | ||||
| /.sass-cache | ||||
| # Miscellaneous | ||||
| /.angular/cache | ||||
| .sass-cache/ | ||||
| /connect.lock | ||||
| /coverage | ||||
| /libpeerconnection.log | ||||
| npm-debug.log | ||||
| yarn-error.log | ||||
| testem.log | ||||
| /typings | ||||
| 
 | ||||
| # System Files | ||||
| # System files | ||||
| .DS_Store | ||||
| Thumbs.db | ||||
|  | ||||
							
								
								
									
										4
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								.vscode/extensions.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| { | ||||
|   // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 | ||||
|   "recommendations": ["angular.ng-template"] | ||||
| } | ||||
							
								
								
									
										20
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| { | ||||
|   // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||||
|   "version": "0.2.0", | ||||
|   "configurations": [ | ||||
|     { | ||||
|       "name": "ng serve", | ||||
|       "type": "chrome", | ||||
|       "request": "launch", | ||||
|       "preLaunchTask": "npm: start", | ||||
|       "url": "http://localhost:4200/" | ||||
|     }, | ||||
|     { | ||||
|       "name": "ng test", | ||||
|       "type": "chrome", | ||||
|       "request": "launch", | ||||
|       "preLaunchTask": "npm: test", | ||||
|       "url": "http://localhost:9876/debug.html" | ||||
|     } | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										42
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| { | ||||
|   // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 | ||||
|   "version": "2.0.0", | ||||
|   "tasks": [ | ||||
|     { | ||||
|       "type": "npm", | ||||
|       "script": "start", | ||||
|       "isBackground": true, | ||||
|       "problemMatcher": { | ||||
|         "owner": "typescript", | ||||
|         "pattern": "$tsc", | ||||
|         "background": { | ||||
|           "activeOnStart": true, | ||||
|           "beginsPattern": { | ||||
|             "regexp": "(.*?)" | ||||
|           }, | ||||
|           "endsPattern": { | ||||
|             "regexp": "bundle generation complete" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     { | ||||
|       "type": "npm", | ||||
|       "script": "test", | ||||
|       "isBackground": true, | ||||
|       "problemMatcher": { | ||||
|         "owner": "typescript", | ||||
|         "pattern": "$tsc", | ||||
|         "background": { | ||||
|           "activeOnStart": true, | ||||
|           "beginsPattern": { | ||||
|             "regexp": "(.*?)" | ||||
|           }, | ||||
|           "endsPattern": { | ||||
|             "regexp": "bundle generation complete" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										152
									
								
								angular.json
									
									
									
									
									
								
							
							
						
						
									
										152
									
								
								angular.json
									
									
									
									
									
								
							| @ -3,124 +3,6 @@ | ||||
|   "version": 1, | ||||
|   "newProjectRoot": "projects", | ||||
|   "projects": { | ||||
|     "demo": { | ||||
|       "projectType": "application", | ||||
|       "schematics": {}, | ||||
|       "root": "", | ||||
|       "sourceRoot": "src", | ||||
|       "prefix": "app", | ||||
|       "architect": { | ||||
|         "build": { | ||||
|           "builder": "@angular-devkit/build-angular:browser", | ||||
|           "options": { | ||||
|             "outputPath": "dist/data", | ||||
|             "index": "src/index.html", | ||||
|             "main": "src/main.ts", | ||||
|             "polyfills": "src/polyfills.ts", | ||||
|             "tsConfig": "tsconfig.app.json", | ||||
|             "aot": false, | ||||
|             "assets": [ | ||||
|               "src/favicon.ico", | ||||
|               "src/assets" | ||||
|             ], | ||||
|             "styles": [ | ||||
|               "src/styles.css" | ||||
|             ], | ||||
|             "scripts": [] | ||||
|           }, | ||||
|           "configurations": { | ||||
|             "production": { | ||||
|               "fileReplacements": [ | ||||
|                 { | ||||
|                   "replace": "src/environments/environment.ts", | ||||
|                   "with": "src/environments/environment.prod.ts" | ||||
|                 } | ||||
|               ], | ||||
|               "optimization": true, | ||||
|               "outputHashing": "all", | ||||
|               "sourceMap": false, | ||||
|               "extractCss": true, | ||||
|               "namedChunks": false, | ||||
|               "aot": true, | ||||
|               "extractLicenses": true, | ||||
|               "vendorChunk": false, | ||||
|               "buildOptimizer": true, | ||||
|               "budgets": [ | ||||
|                 { | ||||
|                   "type": "initial", | ||||
|                   "maximumWarning": "2mb", | ||||
|                   "maximumError": "5mb" | ||||
|                 }, | ||||
|                 { | ||||
|                   "type": "anyComponentStyle", | ||||
|                   "maximumWarning": "6kb", | ||||
|                   "maximumError": "10kb" | ||||
|                 } | ||||
|               ] | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         "serve": { | ||||
|           "builder": "@angular-devkit/build-angular:dev-server", | ||||
|           "options": { | ||||
|             "browserTarget": "data:build" | ||||
|           }, | ||||
|           "configurations": { | ||||
|             "production": { | ||||
|               "browserTarget": "data:build:production" | ||||
|             } | ||||
|           } | ||||
|         }, | ||||
|         "extract-i18n": { | ||||
|           "builder": "@angular-devkit/build-angular:extract-i18n", | ||||
|           "options": { | ||||
|             "browserTarget": "data:build" | ||||
|           } | ||||
|         }, | ||||
|         "test": { | ||||
|           "builder": "@angular-devkit/build-angular:karma", | ||||
|           "options": { | ||||
|             "main": "src/test.ts", | ||||
|             "polyfills": "src/polyfills.ts", | ||||
|             "tsConfig": "tsconfig.spec.json", | ||||
|             "karmaConfig": "karma.conf.js", | ||||
|             "assets": [ | ||||
|               "src/favicon.ico", | ||||
|               "src/assets" | ||||
|             ], | ||||
|             "styles": [ | ||||
|               "src/styles.css" | ||||
|             ], | ||||
|             "scripts": [] | ||||
|           } | ||||
|         }, | ||||
|         "lint": { | ||||
|           "builder": "@angular-devkit/build-angular:tslint", | ||||
|           "options": { | ||||
|             "tsConfig": [ | ||||
|               "tsconfig.app.json", | ||||
|               "tsconfig.spec.json", | ||||
|               "e2e/tsconfig.json" | ||||
|             ], | ||||
|             "exclude": [ | ||||
|               "**/node_modules/**" | ||||
|             ] | ||||
|           } | ||||
|         }, | ||||
|         "e2e": { | ||||
|           "builder": "@angular-devkit/build-angular:protractor", | ||||
|           "options": { | ||||
|             "protractorConfig": "e2e/protractor.conf.js", | ||||
|             "devServerTarget": "data:serve" | ||||
|           }, | ||||
|           "configurations": { | ||||
|             "production": { | ||||
|               "devServerTarget": "data:serve:production" | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "data": { | ||||
|       "projectType": "library", | ||||
|       "root": "projects/data", | ||||
| @ -128,33 +10,31 @@ | ||||
|       "prefix": "lib", | ||||
|       "architect": { | ||||
|         "build": { | ||||
|           "builder": "@angular-devkit/build-ng-packagr:build", | ||||
|           "builder": "@angular-devkit/build-angular:ng-packagr", | ||||
|           "options": { | ||||
|             "tsConfig": "projects/data/tsconfig.lib.json", | ||||
|             "project": "projects/data/ng-package.json" | ||||
|           } | ||||
|           }, | ||||
|           "configurations": { | ||||
|             "production": { | ||||
|               "tsConfig": "projects/data/tsconfig.lib.prod.json" | ||||
|             }, | ||||
|             "development": { | ||||
|               "tsConfig": "projects/data/tsconfig.lib.json" | ||||
|             } | ||||
|           }, | ||||
|           "defaultConfiguration": "production" | ||||
|         }, | ||||
|         "test": { | ||||
|           "builder": "@angular-devkit/build-angular:karma", | ||||
|           "options": { | ||||
|             "main": "projects/data/src/test.ts", | ||||
|             "tsConfig": "projects/data/tsconfig.spec.json", | ||||
|             "karmaConfig": "projects/data/karma.conf.js" | ||||
|           } | ||||
|         }, | ||||
|         "lint": { | ||||
|           "builder": "@angular-devkit/build-angular:tslint", | ||||
|           "options": { | ||||
|             "tsConfig": [ | ||||
|               "projects/data/tsconfig.lib.json", | ||||
|               "projects/data/tsconfig.spec.json" | ||||
|             ], | ||||
|             "exclude": [ | ||||
|               "**/node_modules/**" | ||||
|             "polyfills": [ | ||||
|               "zone.js", | ||||
|               "zone.js/testing" | ||||
|             ] | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }}, | ||||
|   "defaultProject": "data" | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										12
									
								
								browserslist
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								browserslist
									
									
									
									
									
								
							| @ -1,12 +0,0 @@ | ||||
| # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. | ||||
| # For additional information regarding the format and rule options, please see: | ||||
| # https://github.com/browserslist/browserslist#queries | ||||
| 
 | ||||
| # You can see what browsers were selected by your queries by running: | ||||
| #   npx browserslist | ||||
| 
 | ||||
| > 0.5% | ||||
| last 2 versions | ||||
| Firefox ESR | ||||
| not dead | ||||
| not IE 9-11 # For IE 9-11 support, remove 'not'. | ||||
| @ -1,32 +0,0 @@ | ||||
| // @ts-check
 | ||||
| // Protractor configuration file, see link for more information
 | ||||
| // https://github.com/angular/protractor/blob/master/lib/config.ts
 | ||||
| 
 | ||||
| const { SpecReporter } = require('jasmine-spec-reporter'); | ||||
| 
 | ||||
| /** | ||||
|  * @type { import("protractor").Config } | ||||
|  */ | ||||
| exports.config = { | ||||
|   allScriptsTimeout: 11000, | ||||
|   specs: [ | ||||
|     './src/**/*.e2e-spec.ts' | ||||
|   ], | ||||
|   capabilities: { | ||||
|     'browserName': 'chrome' | ||||
|   }, | ||||
|   directConnect: true, | ||||
|   baseUrl: 'http://localhost:4200/', | ||||
|   framework: 'jasmine', | ||||
|   jasmineNodeOpts: { | ||||
|     showColors: true, | ||||
|     defaultTimeoutInterval: 30000, | ||||
|     print: function() {} | ||||
|   }, | ||||
|   onPrepare() { | ||||
|     require('ts-node').register({ | ||||
|       project: require('path').join(__dirname, './tsconfig.json') | ||||
|     }); | ||||
|     jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); | ||||
|   } | ||||
| }; | ||||
| @ -1,23 +0,0 @@ | ||||
| import { AppPage } from './app.po'; | ||||
| import { browser, logging } from 'protractor'; | ||||
| 
 | ||||
| describe('workspace-project App', () => { | ||||
|   let page: AppPage; | ||||
| 
 | ||||
|   beforeEach(() => { | ||||
|     page = new AppPage(); | ||||
|   }); | ||||
| 
 | ||||
|   it('should display welcome message', () => { | ||||
|     page.navigateTo(); | ||||
|     expect(page.getTitleText()).toEqual('data app is running!'); | ||||
|   }); | ||||
| 
 | ||||
|   afterEach(async () => { | ||||
|     // Assert that there are no errors emitted from the browser
 | ||||
|     const logs = await browser.manage().logs().get(logging.Type.BROWSER); | ||||
|     expect(logs).not.toContain(jasmine.objectContaining({ | ||||
|       level: logging.Level.SEVERE, | ||||
|     } as logging.Entry)); | ||||
|   }); | ||||
| }); | ||||
| @ -1,11 +0,0 @@ | ||||
| import { browser, by, element } from 'protractor'; | ||||
| 
 | ||||
| export class AppPage { | ||||
|   navigateTo() { | ||||
|     return browser.get(browser.baseUrl) as Promise<any>; | ||||
|   } | ||||
| 
 | ||||
|   getTitleText() { | ||||
|     return element(by.css('app-root .content span')).getText() as Promise<string>; | ||||
|   } | ||||
| } | ||||
| @ -1,13 +0,0 @@ | ||||
| { | ||||
|   "extends": "../tsconfig.json", | ||||
|   "compilerOptions": { | ||||
|     "outDir": "../out-tsc/e2e", | ||||
|     "module": "commonjs", | ||||
|     "target": "es5", | ||||
|     "types": [ | ||||
|       "jasmine", | ||||
|       "jasminewd2", | ||||
|       "node" | ||||
|     ] | ||||
|   } | ||||
| } | ||||
| @ -1,32 +0,0 @@ | ||||
| // 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/data'), | ||||
|       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 | ||||
|   }); | ||||
| }; | ||||
							
								
								
									
										13710
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										13710
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										76
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								package.json
									
									
									
									
									
								
							| @ -1,51 +1,43 @@ | ||||
| { | ||||
|   "name": "data", | ||||
|   "version": "0.0.30", | ||||
|   "name": "ts-data", | ||||
|   "version": "0.0.0", | ||||
|   "scripts": { | ||||
|     "serve": "ng serve", | ||||
|     "build": "ng build data", | ||||
|     "publish": "npm publish dist/data --registry=https://registry.npmjs.org/ --access public" | ||||
|     "ng": "ng", | ||||
|     "start": "ng serve", | ||||
|     "build": "ng build", | ||||
|     "watch": "ng build --watch --configuration development", | ||||
|     "test": "ng test", | ||||
| 
 | ||||
|     "build-data": "ng build data --configuration production", | ||||
|     "publish-data": "npm publish dist/openharbor/data --access public" | ||||
|   }, | ||||
|   "publishConfig": { | ||||
|     "registry": "https://registry.npmjs.org" | ||||
|   }, | ||||
|   "private": false, | ||||
|   "private": true, | ||||
|   "dependencies": { | ||||
|     "@angular/animations": "~8.2.4", | ||||
|     "@angular/common": "~8.2.4", | ||||
|     "@angular/compiler": "~8.2.4", | ||||
|     "@angular/core": "~8.2.4", | ||||
|     "@angular/forms": "~8.2.4", | ||||
|     "@angular/platform-browser": "~8.2.4", | ||||
|     "@angular/platform-browser-dynamic": "~8.2.4", | ||||
|     "@angular/router": "~8.2.4", | ||||
|     "rxjs": "~6.5.3", | ||||
|     "tslib": "^1.10.0", | ||||
|     "zone.js": "~0.9.1" | ||||
|     "@angular/animations": "^18.0.0", | ||||
|     "@angular/common": "^18.0.0", | ||||
|     "@angular/compiler": "^18.0.0", | ||||
|     "@angular/core": "^18.0.0", | ||||
|     "@angular/forms": "^18.0.0", | ||||
|     "@angular/platform-browser": "^18.0.0", | ||||
|     "@angular/platform-browser-dynamic": "^18.0.0", | ||||
|     "@angular/router": "^18.0.0", | ||||
|     "rxjs": "~7.8.0", | ||||
|     "tslib": "^2.3.0", | ||||
|     "zone.js": "~0.14.3" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@angular-devkit/build-angular": "~0.803.3", | ||||
|     "@angular-devkit/build-ng-packagr": "~0.803.3", | ||||
|     "@angular/cli": "~8.3.3", | ||||
|     "@angular/compiler-cli": "~8.2.4", | ||||
|     "@angular/language-service": "~8.2.4", | ||||
|     "@types/node": "~8.9.4", | ||||
|     "@types/jasmine": "~3.3.8", | ||||
|     "@types/jasminewd2": "~2.0.3", | ||||
|     "codelyzer": "^5.0.0", | ||||
|     "jasmine-core": "~3.4.0", | ||||
|     "jasmine-spec-reporter": "~4.2.1", | ||||
|     "karma": "~4.1.0", | ||||
|     "karma-chrome-launcher": "~2.2.0", | ||||
|     "karma-coverage-istanbul-reporter": "~2.0.1", | ||||
|     "karma-jasmine": "~2.0.1", | ||||
|     "karma-jasmine-html-reporter": "^1.4.0", | ||||
|     "ng-packagr": "^5.4.0", | ||||
|     "protractor": "~5.4.0", | ||||
|     "ts-node": "~7.0.0", | ||||
|     "tsickle": "^0.37.0", | ||||
|     "tslint": "~5.15.0", | ||||
|     "typescript": "~3.5.3" | ||||
|     "@angular-devkit/build-angular": "^18.2.2", | ||||
|     "@angular/cli": "^18.0.7", | ||||
|     "@angular/compiler-cli": "^18.0.0", | ||||
|     "@types/jasmine": "~5.1.0", | ||||
|     "jasmine-core": "~5.1.0", | ||||
|     "karma": "~6.4.0", | ||||
|     "karma-chrome-launcher": "~3.2.0", | ||||
|     "karma-coverage": "~2.2.0", | ||||
|     "karma-jasmine": "~5.1.0", | ||||
|     "karma-jasmine-html-reporter": "~2.1.0", | ||||
|     "ng-packagr": "^18.2.0", | ||||
|     "typescript": "~5.4.2" | ||||
|   }, | ||||
|   "packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610" | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| { | ||||
|   "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", | ||||
|   "dest": "../../dist/data", | ||||
|   "dest": "../../dist/openharbor/data", | ||||
|   "lib": { | ||||
|     "entryFile": "src/public-api.ts" | ||||
|   } | ||||
|  | ||||
| @ -2,10 +2,11 @@ | ||||
|   "name": "@openharbor/data", | ||||
|   "version": "1.0.0-alpha.1", | ||||
|   "repository": "https://git.openharbor.io/Open-Harbor/ts-data", | ||||
|   "publishConfig": { | ||||
|     "registry": "https://registry.npmjs.org" | ||||
|   }, | ||||
|   "peerDependencies": { | ||||
|     "rxjs": "^6.5.3" | ||||
|   } | ||||
|     "rxjs": "^6.5.3 || ^7.4.0" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "tslib": "^2.3.0" | ||||
|   }, | ||||
|   "sideEffects": false | ||||
| } | ||||
|  | ||||
| @ -1,284 +0,0 @@ | ||||
| import { Observable, of, Observer, BehaviorSubject, throwError, Subject } from 'rxjs'; | ||||
| import { IDataSource } from './IDataSource'; | ||||
| import { IQueryExecutionResult, IQueryExecutionGroupResult, IFilter, ISort, IAggregate, IGroup, IQueryCriteria } from './models'; | ||||
| import { finalize, catchError, map } from 'rxjs/operators'; | ||||
| import { IDataSourceOptions, IResolveCommandModelEvent } from '../public-api'; | ||||
| import { IDataSourceErrorMessage } from './IDataSourceErrorMessage'; | ||||
| import { IDataSourceValidationError } from './IDataSourceValidationError'; | ||||
| import { IDataSourceError } from './IDataSourceError'; | ||||
| import { IDataSourceNotifyMessage } from './IDataSourceNotifyMessage'; | ||||
| import { IDataSourceCommandStarted } from './IDataSourceCommandStarted'; | ||||
| 
 | ||||
| export class DataSource<TModel> implements IDataSource<TModel> | ||||
| { | ||||
|     data: IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel> = null; | ||||
| 
 | ||||
|     protected _dataSubject: BehaviorSubject<IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>> = new BehaviorSubject(null); | ||||
|     protected _loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject(false); | ||||
|     protected _validationSubject: Subject<IDataSourceValidationError> = new Subject(); | ||||
|     protected _commandStartedSubject: Subject<IDataSourceCommandStarted> = new Subject(); | ||||
|     protected _notifyMessageSubject: Subject<IDataSourceNotifyMessage> = new Subject(); | ||||
| 
 | ||||
|     protected _data$: Observable<IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>>; | ||||
|     protected _loading$: Observable<boolean>; | ||||
|     protected _validationError$: Observable<IDataSourceValidationError>; | ||||
|     protected _notifyMessage$: Observable<IDataSourceNotifyMessage>; | ||||
|     protected _commandStarted$: Observable<IDataSourceCommandStarted>; | ||||
| 
 | ||||
|     protected _criteria: IQueryCriteria = { | ||||
|         page: null, | ||||
|         pageSize: null, | ||||
|         filters: [], | ||||
|         aggregates: [], | ||||
|         groups: [], | ||||
|         sorts: [] | ||||
|     }; | ||||
| 
 | ||||
|     get data$() { | ||||
|         if (!this._data$) | ||||
|             this._data$ = this._dataSubject.asObservable(); | ||||
| 
 | ||||
|         return this._data$; | ||||
|     } | ||||
| 
 | ||||
|     get loading$() { | ||||
|         if (!this._loading$) | ||||
|             this._loading$ = this._loadingSubject.asObservable(); | ||||
| 
 | ||||
|         return this._loading$; | ||||
|     } | ||||
| 
 | ||||
|     get validationError$() { | ||||
|         if (!this._validationError$) | ||||
|             this._validationError$ = this._validationSubject.asObservable(); | ||||
| 
 | ||||
|         return this._validationError$; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     get commandStarted$() { | ||||
|         if (!this._commandStarted$) | ||||
|             this._commandStarted$ = this._commandStartedSubject.asObservable(); | ||||
| 
 | ||||
|         return this._commandStarted$; | ||||
|     } | ||||
| 
 | ||||
|     get notifyMessage$() { | ||||
|         if (!this._notifyMessage$) | ||||
|             this._notifyMessage$ = this._notifyMessageSubject.asObservable(); | ||||
| 
 | ||||
|         return this._notifyMessage$; | ||||
|     } | ||||
| 
 | ||||
|     constructor(public options: IDataSourceOptions<TModel>) { | ||||
|         this._initCriteria(); | ||||
|     } | ||||
| 
 | ||||
|     clear() { | ||||
|         this.data = null; | ||||
|         this._dataSubject.next(null); | ||||
|     } | ||||
| 
 | ||||
|     updateData(value: IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>) { | ||||
|         this.data = value; | ||||
|         this._dataSubject.next(this.data); | ||||
|     } | ||||
| 
 | ||||
|     replaceDataWithArray(items: TModel[]) { | ||||
|         this.data = { | ||||
|             totalRecords: items.length, | ||||
|             numberOfPages: null, | ||||
|             groups: null, | ||||
|             aggregates: null, | ||||
|             data: items | ||||
|         }; | ||||
|         this._dataSubject.next(this.data); | ||||
|     } | ||||
| 
 | ||||
|     replaceDataWithSingle(item: TModel) { | ||||
|         this.data = { | ||||
|             totalRecords: 1, | ||||
|             numberOfPages: null, | ||||
|             groups: null, | ||||
|             aggregates: null, | ||||
|             data: [item] | ||||
|         }; | ||||
|         this._dataSubject.next(this.data); | ||||
|     } | ||||
| 
 | ||||
|     protected _initCriteria() { | ||||
|         if (!this.options.defaultCriteria) | ||||
|             return; | ||||
| 
 | ||||
|         const copy: IQueryCriteria = JSON.parse(JSON.stringify(this.options.defaultCriteria)); | ||||
|         this._criteria.page = copy.page || this._criteria.page; | ||||
|         this._criteria.pageSize = copy.pageSize || this._criteria.pageSize; | ||||
|         this._criteria.filters = copy.filters || this._criteria.filters; | ||||
|         this._criteria.groups = copy.groups || this._criteria.groups; | ||||
|         this._criteria.aggregates = copy.aggregates || this._criteria.aggregates; | ||||
|         this._criteria.sorts = copy.sorts || this._criteria.sorts; | ||||
|     } | ||||
| 
 | ||||
|     resolveIdField<TKeyType extends any>(model: TModel): TKeyType { | ||||
| 
 | ||||
|         if (this.options.idField) | ||||
|             return model[this.options.idField]; | ||||
| 
 | ||||
|         if (this.options.resolveIdField) | ||||
|             return this.options.resolveIdField(model); | ||||
| 
 | ||||
|         throw new Error("Must specify an id field or supply a method to resolve the id field."); | ||||
|     } | ||||
| 
 | ||||
|     resolveCommandModelByName<T extends any>(event: IResolveCommandModelEvent<TModel>) : Observable<T> { | ||||
|         if (!this.options.transport.commands.hasOwnProperty(event.command)) | ||||
|             return throwError(<IDataSourceErrorMessage>{ | ||||
|                 type: 'message', | ||||
|                 message: `command with name ${event.command} not found` | ||||
|             }); | ||||
| 
 | ||||
|         const commandOptions = this.options.transport.commands[event.command]; | ||||
|         if (commandOptions.resolveCommandModel) | ||||
|             return commandOptions.resolveCommandModel(event); | ||||
| 
 | ||||
|         const noResolveMethod: any = event.model || {}; | ||||
|         return of<T>(noResolveMethod as T); | ||||
|     } | ||||
| 
 | ||||
|     executeCommandByName<TCommand, TResult>(name: string, command: TCommand) : Observable<TResult> { | ||||
|         if (!this.options.transport.commands.hasOwnProperty(name)) | ||||
|             return throwError(`command with name ${name} not found`); | ||||
| 
 | ||||
|         this._commandStartedSubject.next({ | ||||
|             name: name, command: command | ||||
|         }); | ||||
| 
 | ||||
|         return this.options.transport.commands[name].adapter.handle(command).pipe( | ||||
|             map(t => { | ||||
|                 this._notifyMessageSubject.next({ | ||||
|                     type: 'success', | ||||
|                     message: 'COMMAND_EXECUTED_SUCCESSFULLY', | ||||
|                     messageParams: { | ||||
|                         command: name | ||||
|                     } | ||||
|                 }); | ||||
|                 return t; | ||||
|             }), | ||||
|             catchError((err: IDataSourceError) => { | ||||
|                 if (err.type == 'message') | ||||
|                     this._notifyMessageSubject.next({ | ||||
|                         type: 'error', | ||||
|                         message: (err as IDataSourceErrorMessage).message | ||||
|                     }); | ||||
|                 else if(err.type == 'validation') | ||||
|                     this._validationSubject.next(err as IDataSourceValidationError); | ||||
| 
 | ||||
|                 return throwError(err); | ||||
|             }) | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     private _query() : Observable<IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>> { | ||||
|       return new Observable<IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>>((o: Observer<IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>>) => { | ||||
|         this._loadingSubject.next(true); | ||||
|         this.options.transport.query.adapter.handle(this._criteria) | ||||
|           .pipe( | ||||
|             finalize(() => { | ||||
|               o.complete(); | ||||
|               this._loadingSubject.next(false); | ||||
|             }) | ||||
|           ) | ||||
|           .subscribe( | ||||
|             result => { | ||||
|               this.data = result; | ||||
|               o.next(result); | ||||
|               this._dataSubject.next(this.data); | ||||
|               this._notifyMessageSubject.next({ | ||||
|                 message: 'NEW_DATA_READ_SUCCESSFULLY', | ||||
|                 type: 'info' | ||||
|               }); | ||||
|             }, | ||||
|             err => { | ||||
|               o.error(err); | ||||
|               this._notifyMessageSubject.next({ | ||||
|                 message: 'UNEXPECTED_ERROR_OCCURRED', | ||||
|                 type: 'error' | ||||
|               }); | ||||
|             } | ||||
|           ); | ||||
|       }); | ||||
|     } | ||||
| 
 | ||||
|     query<TQuery extends IQueryCriteria>(query: TQuery) { | ||||
|         this._criteria.page = query.page === undefined ? this._criteria.page:query.page; | ||||
|         this._criteria.pageSize = query.pageSize === undefined ? this._criteria.pageSize: query.pageSize; | ||||
|         this._criteria.filters = query.filters || this._criteria.filters; | ||||
|         this._criteria.groups = query.groups || this._criteria.groups; | ||||
|         this._criteria.aggregates = query.aggregates || this._criteria.aggregates; | ||||
|         this._criteria.sorts = query.sorts || this._criteria.sorts; | ||||
|         return this.refresh(); | ||||
|     } | ||||
| 
 | ||||
|     executeQuery<TQuery extends IQueryCriteria>(query: TQuery): Observable<IQueryExecutionGroupResult<TModel>>{ | ||||
|         return this.options.transport.query.adapter.handle(query); | ||||
|     } | ||||
| 
 | ||||
|     refresh() { | ||||
|         return this._query() | ||||
|           .subscribe(); | ||||
|     } | ||||
| 
 | ||||
|     get sorts() { | ||||
|         return this._criteria.sorts; | ||||
|     } | ||||
| 
 | ||||
|     set sorts(value: ISort[]) { | ||||
|         this._criteria.sorts = value; | ||||
|         this.refresh(); | ||||
|     } | ||||
| 
 | ||||
|     get filters() { | ||||
|         return this._criteria.filters; | ||||
|     } | ||||
| 
 | ||||
|     set filters(value: IFilter[]) { | ||||
|         this._criteria.filters = value; | ||||
|         this.refresh(); | ||||
|     } | ||||
| 
 | ||||
|     get groups() { | ||||
|         return this._criteria.groups; | ||||
|     } | ||||
| 
 | ||||
|     set groups(value: IGroup[]) { | ||||
|         this._criteria.groups = value; | ||||
|         this.refresh(); | ||||
|     } | ||||
| 
 | ||||
|     get aggregates() { | ||||
|         return this._criteria.aggregates; | ||||
|     } | ||||
| 
 | ||||
|     set aggregates(value: IAggregate[]) { | ||||
|         this._criteria.aggregates = value; | ||||
|         this.refresh(); | ||||
|     } | ||||
| 
 | ||||
|     get pageSize() { | ||||
|         return this._criteria.pageSize; | ||||
|     } | ||||
| 
 | ||||
|     set pageSize(value: number) { | ||||
|         this._criteria.pageSize = value; | ||||
|         this.refresh(); | ||||
|     } | ||||
| 
 | ||||
|     get page() { | ||||
|         return this._criteria.page; | ||||
|     } | ||||
| 
 | ||||
|     set page(value: number) { | ||||
|         this._criteria.page = value; | ||||
|         this.refresh(); | ||||
|     } | ||||
| } | ||||
| @ -1,4 +0,0 @@ | ||||
| import { IQueryCriteria, IQueryExecutionResult, IQueryExecutionGroupResult } from './models'; | ||||
| import { IQueryAdapter } from "./IQueryAdapter"; | ||||
| export interface IAdvanceQueryAdapter<TQuery extends IQueryCriteria, TResult> extends IQueryAdapter<TQuery, IQueryExecutionResult<TResult> & IQueryExecutionGroupResult<TResult>> { | ||||
| } | ||||
| @ -1,4 +0,0 @@ | ||||
| import { Observable } from 'rxjs'; | ||||
| export interface ICommandAdapter<TCommand, TResult> { | ||||
|     handle(command: TCommand): Observable<TResult>; | ||||
| } | ||||
| @ -1,35 +0,0 @@ | ||||
| import { Observable } from "rxjs"; | ||||
| import { ISort, IFilter, IGroup, IAggregate, IQueryExecutionResult, IQueryExecutionGroupResult, IQueryCriteria } from "./models"; | ||||
| import { IResolveCommandModelEvent } from "./IResolveCommandModelEvent"; | ||||
| import { IDataSourceValidationError } from './IDataSourceValidationError'; | ||||
| import { IDataSourceNotifyMessage } from './IDataSourceNotifyMessage'; | ||||
| import { IDataSourceCommandStarted } from "./IDataSourceCommandStarted"; | ||||
| 
 | ||||
| export interface IDataSource<TModel> | ||||
| { | ||||
|     resolveCommandModelByName<T extends any>(event: IResolveCommandModelEvent<TModel>) : Observable<T>; | ||||
|     executeCommandByName<TCommand, TResult>(name: string, command: TCommand) : Observable<TResult>; | ||||
|     query<TQuery extends IQueryCriteria>(query: TQuery); | ||||
|     executeQuery<TQuery extends IQueryCriteria>(query: TQuery): Observable<IQueryExecutionGroupResult<TModel> & IQueryExecutionGroupResult<TModel>>; | ||||
|     refresh(); | ||||
|     resolveIdField<TKeyType extends any>(model: TModel) : TKeyType; | ||||
|     clear(); | ||||
|     updateData(value: IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>); | ||||
|     replaceDataWithArray(items: TModel[]); | ||||
|     replaceDataWithSingle(item: TModel); | ||||
| 
 | ||||
|     data$: Observable<IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>>; | ||||
|     loading$: Observable<boolean>; | ||||
|     validationError$: Observable<IDataSourceValidationError>; | ||||
|     notifyMessage$: Observable<IDataSourceNotifyMessage>; | ||||
|     commandStarted$: Observable<IDataSourceCommandStarted>; | ||||
| 
 | ||||
|     data: IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>; | ||||
| 
 | ||||
|     sorts: ISort[]; | ||||
|     filters: IFilter[]; | ||||
|     groups: IGroup[]; | ||||
|     aggregates: IAggregate[]; | ||||
|     pageSize: number; | ||||
|     page: number; | ||||
| } | ||||
| @ -1,7 +0,0 @@ | ||||
| import { Observable } from "rxjs"; | ||||
| import { ICommandAdapter } from "./ICommandAdapter"; | ||||
| import { IResolveCommandModelEvent } from "./IResolveCommandModelEvent"; | ||||
| export interface IDataSourceCommandAdapterOptions<TModel> { | ||||
|     adapter: ICommandAdapter<any, any>; | ||||
|     resolveCommandModel?: (event: IResolveCommandModelEvent<TModel>) => Observable<any>; | ||||
| } | ||||
| @ -1,5 +0,0 @@ | ||||
| 
 | ||||
| export interface IDataSourceCommandStarted { | ||||
|     name: string; | ||||
|     command: any; | ||||
| } | ||||
| @ -1,4 +0,0 @@ | ||||
| export interface IDataSourceError { | ||||
|     type: 'message' | 'validation'; | ||||
| } | ||||
| 
 | ||||
| @ -1,7 +0,0 @@ | ||||
| import { IDataSourceError } from './IDataSourceError'; | ||||
| 
 | ||||
| export interface IDataSourceErrorMessage extends IDataSourceError { | ||||
|     message: string; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -1,5 +0,0 @@ | ||||
| export interface IDataSourceNotifyMessage { | ||||
|     type: 'warning' | 'info' | 'success' | 'error'; | ||||
|     message: string; | ||||
|     messageParams?: any; | ||||
| } | ||||
| @ -1,18 +0,0 @@ | ||||
| import { IDataSourceQueryAdapterOptions } from "./IDataSourceQueryAdapterOptions"; | ||||
| import { IDataSourceCommandAdapterOptions } from "./IDataSourceCommandAdapterOptions"; | ||||
| import { IQueryCriteria } from "./models"; | ||||
| 
 | ||||
| 
 | ||||
| export interface IDataSourceOptions<TModel> { | ||||
|     transport: IDataSourceTransportOptions<TModel>; | ||||
|     idField?: string; | ||||
|     resolveIdField?: (model: TModel) => any; | ||||
|     defaultCriteria: IQueryCriteria; | ||||
| } | ||||
| 
 | ||||
| export interface IDataSourceTransportOptions<TModel> { | ||||
|     query: IDataSourceQueryAdapterOptions<TModel>; | ||||
|     commands: { | ||||
|         [name: string]: IDataSourceCommandAdapterOptions<TModel>; | ||||
|     }; | ||||
| } | ||||
| @ -1,5 +0,0 @@ | ||||
| import { IAdvanceQueryAdapter } from "./IAdvanceQueryAdapter"; | ||||
| 
 | ||||
| export interface IDataSourceQueryAdapterOptions<TModel> { | ||||
|     adapter: IAdvanceQueryAdapter<any, TModel>; | ||||
| } | ||||
| @ -1,6 +0,0 @@ | ||||
| import { IDataSourceError } from './IDataSourceError'; | ||||
| 
 | ||||
| export interface IDataSourceValidationError extends IDataSourceError | ||||
| { | ||||
|     errors: { [field: string]: string[]; } | ||||
| } | ||||
| @ -1,4 +0,0 @@ | ||||
| import { Observable } from 'rxjs'; | ||||
| export interface IQueryAdapter<TQuery, TResult> { | ||||
|     handle(query: TQuery): Observable<TResult>; | ||||
| } | ||||
| @ -1,5 +0,0 @@ | ||||
| export interface IResolveCommandModelEvent<TModel> { | ||||
|     command: string; | ||||
|     model: TModel; | ||||
|     params?: any; | ||||
| } | ||||
							
								
								
									
										15
									
								
								projects/data/src/lib/abstractions/command.abstraction.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								projects/data/src/lib/abstractions/command.abstraction.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| import {Observable} from 'rxjs'; | ||||
| 
 | ||||
| export interface ICommand { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| export interface ICommandAdapter<TCommand extends {}, TResult> { | ||||
|   handle(command: TCommand): Observable<TResult>; | ||||
| } | ||||
| 
 | ||||
| export interface IResolveCommandModelEvent<TModel> { | ||||
|   command: string; | ||||
|   model: TModel; | ||||
|   params?: any; | ||||
| } | ||||
| @ -0,0 +1,89 @@ | ||||
| import {Observable, Subscription} from 'rxjs'; | ||||
| import {ICommand, ICommandAdapter, IResolveCommandModelEvent} from './command.abstraction'; | ||||
| import { | ||||
|   IAdvanceQueryAdapter, | ||||
|   IAggregate, | ||||
|   IFilter, | ||||
|   IGroup, | ||||
|   IQueryCriteria, | ||||
|   IQueryExecutionGroupResult, | ||||
|   IQueryExecutionResult, | ||||
|   ISort | ||||
| } from './query.abstraction'; | ||||
| 
 | ||||
| export interface IDataSource<TQuery extends IQueryCriteria, TModel> | ||||
| { | ||||
|   resolveCommandModelByName<TCommand extends ICommand>(event: IResolveCommandModelEvent<TModel>) : Observable<TCommand>; | ||||
|   executeCommandByName<TCommand extends ICommand, TResult>(name: string, command: TCommand) : Observable<TResult>; | ||||
|   query(query: TQuery): Subscription; | ||||
|   executeQuery(query: TQuery): Observable<IQueryExecutionGroupResult<TModel>>; | ||||
|   refresh(): Subscription; | ||||
|   resolveIdField(model: TModel) : TModel[keyof TModel]; | ||||
|   clear(): void; | ||||
|   updateData(value: IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>): void; | ||||
|   replaceDataWithArray(items: TModel[]): void; | ||||
|   replaceDataWithSingle(item: TModel): void; | ||||
| 
 | ||||
|   data$: Observable<IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel> | null>; | ||||
|   loading$: Observable<boolean>; | ||||
|   validationError$: Observable<IDataSourceValidationError>; | ||||
|   notifyMessage$: Observable<IDataSourceNotifyMessage>; | ||||
|   commandStarted$: Observable<IDataSourceCommandStarted>; | ||||
| 
 | ||||
|   data?: IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>; | ||||
| 
 | ||||
|   sorts: ISort[]; | ||||
|   filters: IFilter[]; | ||||
|   groups: IGroup[]; | ||||
|   aggregates: IAggregate[]; | ||||
|   pageSize: number; | ||||
|   page: number; | ||||
| } | ||||
| 
 | ||||
| export interface IDataSourceOptions<TQuery extends IQueryCriteria, TResult>{ | ||||
|   transport: IDataSourceTransportOptions<TQuery, TResult>; | ||||
|   idField?: keyof TResult; | ||||
|   resolveIdField?: (model: TResult) => TResult[keyof TResult]; | ||||
|   defaultCriteria: IQueryCriteria; | ||||
| } | ||||
| 
 | ||||
| export interface IDataSourceTransportOptions<TQuery extends IQueryCriteria, TResult> { | ||||
|   query: IDataSourceQueryAdapterOptions<TQuery, TResult>; | ||||
|   commands: { | ||||
|     [name: string]: IDataSourceCommandAdapterOptions<TResult>; | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| export interface IDataSourceQueryAdapterOptions<TQuery extends IQueryCriteria, TResult> { | ||||
|   adapter: IAdvanceQueryAdapter<TQuery, TResult>; | ||||
| } | ||||
| 
 | ||||
| export interface IDataSourceCommandAdapterOptions<TModel> { | ||||
|   adapter: ICommandAdapter<ICommand, any>; | ||||
|   resolveCommandModel?: (event: IResolveCommandModelEvent<TModel>) => Observable<any>; | ||||
| } | ||||
| 
 | ||||
| export interface IDataSourceCommandStarted { | ||||
|   name: string; | ||||
|   command: ICommand; | ||||
| } | ||||
| 
 | ||||
| export interface IDataSourceNotifyMessage { | ||||
|   type: 'warning' | 'info' | 'success' | 'error'; | ||||
|   message: string; | ||||
|   messageParams?: any; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| export interface IDataSourceError { | ||||
|   type: 'message' | 'validation'; | ||||
| } | ||||
| 
 | ||||
| export interface IDataSourceErrorMessage extends IDataSourceError { | ||||
|   message: string; | ||||
| } | ||||
| 
 | ||||
| export interface IDataSourceValidationError extends IDataSourceError | ||||
| { | ||||
|   errors: { [field: string]: string[]; } | ||||
| } | ||||
							
								
								
									
										104
									
								
								projects/data/src/lib/abstractions/query.abstraction.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								projects/data/src/lib/abstractions/query.abstraction.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,104 @@ | ||||
| import {Observable} from 'rxjs'; | ||||
| 
 | ||||
| export interface IQueryAdapter<TQuery extends IQueryCriteria, TResult> { | ||||
|   handle(query: TQuery): Observable<TResult>; | ||||
| } | ||||
| 
 | ||||
| export interface IAdvanceQueryAdapter<TQuery extends IQueryCriteria, TResult> extends IQueryAdapter<TQuery, IQueryExecutionResult<TResult> & IQueryExecutionGroupResult<TResult>> { | ||||
| } | ||||
| 
 | ||||
| export interface IAggregate { | ||||
|   path: string; | ||||
|   type: string; | ||||
| } | ||||
| 
 | ||||
| export interface ISort { | ||||
|   path: string; | ||||
|   ascending?: boolean; | ||||
| } | ||||
| 
 | ||||
| export interface ISimpleFilter extends IFilter { | ||||
|   path: string; | ||||
|   value: any; | ||||
| } | ||||
| 
 | ||||
| export interface IQueryResult<TModel> { | ||||
|   aggregates?: IAggregateResult[]; | ||||
|   data?: TModel[]; | ||||
| } | ||||
| 
 | ||||
| export interface IQueryExecutionResultPaging { | ||||
|   totalRecords: number; | ||||
|   numberOfPages?: number; | ||||
| } | ||||
| 
 | ||||
| export interface IQueryExecutionResult<TRecord> extends IQueryResult<TRecord>, IQueryExecutionResultPaging { | ||||
| } | ||||
| 
 | ||||
| export interface IQueryExecutionGroupResult<TModel> extends IQueryExecutionResult<TModel> { | ||||
|   groups?: IGroupQueryResult<TModel>[]; | ||||
| } | ||||
| 
 | ||||
| export interface IQueryCriteria { | ||||
|   page?: number; | ||||
|   pageSize?: number; | ||||
|   sorts?: ISort[]; | ||||
|   groups?: IGroup[]; | ||||
|   aggregates?: IAggregate[]; | ||||
|   filters?: IFilter[]; | ||||
| } | ||||
| 
 | ||||
| export interface IGroupQueryResult<TModel> extends IQueryResult<TModel> { | ||||
|   groupPath: string; | ||||
|   groupValue: any; | ||||
|   hasSubGroups: boolean; | ||||
|   subGroups?: IGroupQueryResult<TModel>[]; | ||||
| } | ||||
| 
 | ||||
| export interface IGroup { | ||||
|   path: string; | ||||
|   ascending?: boolean; | ||||
| } | ||||
| 
 | ||||
| export interface IFilter { | ||||
|   type: string; | ||||
|   and?: boolean; | ||||
| } | ||||
| 
 | ||||
| export interface IAggregateResult { | ||||
|   path: string; | ||||
|   type: string; | ||||
|   value: any; | ||||
| } | ||||
| 
 | ||||
| export interface ICompositeFilter extends IFilter { | ||||
|   filters: IFilter[]; | ||||
| } | ||||
| 
 | ||||
| export const enum AggregateType { | ||||
|   COUNT = 'Count', | ||||
|   SUM = 'Sum', | ||||
|   AVG = 'Avg', | ||||
|   LONGCOUNT = 'LongCount', | ||||
|   MIN = 'Min', | ||||
|   MAX = 'Max', | ||||
|   FIRST = 'First', | ||||
|   FIRSTORDEFAULT = 'FirstOrDefault', | ||||
|   LAST = 'Last', | ||||
|   LASTORDEFAULT = 'LastOrDefault' | ||||
| } | ||||
| 
 | ||||
| export const enum FilterType { | ||||
|   EQUAL = 'Equal', | ||||
|   CONTAINS = 'Contains', | ||||
|   STARTSWITH = 'StartsWith', | ||||
|   ENDSWITH = 'EndsWith', | ||||
|   COMPOSITE = 'Composite', | ||||
|   NOTEQUAL = 'NotEqual', | ||||
|   GREATERTHAN = 'GreaterThan', | ||||
|   LESSTHANOREQUAL = 'LessThanOrEqual', | ||||
|   GREATERTHANOREQUAL = 'GreaterThanOrEqual', | ||||
|   LESSTHAN ='LessThan', | ||||
|   IN = 'In', | ||||
|   NOTIN = 'NotIn' | ||||
| } | ||||
							
								
								
									
										295
									
								
								projects/data/src/lib/data-source.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								projects/data/src/lib/data-source.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,295 @@ | ||||
| import {BehaviorSubject, Observable, Observer, of, ReplaySubject, Subject, throwError} from 'rxjs'; | ||||
| import {catchError, finalize, map} from 'rxjs/operators'; | ||||
| import { | ||||
|   IDataSource, | ||||
|   IDataSourceCommandStarted, | ||||
|   IDataSourceError, | ||||
|   IDataSourceErrorMessage, | ||||
|   IDataSourceNotifyMessage, | ||||
|   IDataSourceOptions, | ||||
|   IDataSourceValidationError, | ||||
| } from './abstractions/data-source.abstraction'; | ||||
| import { | ||||
|   IAggregate, | ||||
|   IFilter, | ||||
|   IGroup, | ||||
|   IQueryCriteria, | ||||
|   IQueryExecutionGroupResult, | ||||
|   IQueryExecutionResult, | ||||
|   ISort | ||||
| } from './abstractions/query.abstraction'; | ||||
| import {ICommand, IResolveCommandModelEvent} from './abstractions/command.abstraction'; | ||||
| 
 | ||||
| 
 | ||||
| export class DataSource<TQuery extends IQueryCriteria, TModel extends {}> implements IDataSource<TQuery, TModel> | ||||
| { | ||||
|   data?: IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>; | ||||
| 
 | ||||
|   protected _dataSubject: ReplaySubject<IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel> | null> = new ReplaySubject(1); | ||||
|   protected _loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject(false); | ||||
|   protected _validationSubject: Subject<IDataSourceValidationError> = new Subject(); | ||||
|   protected _commandStartedSubject: Subject<IDataSourceCommandStarted> = new Subject(); | ||||
|   protected _notifyMessageSubject: Subject<IDataSourceNotifyMessage> = new Subject(); | ||||
| 
 | ||||
|   protected _data$!: Observable<IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel> | null>; | ||||
|   protected _loading$!: Observable<boolean>; | ||||
|   protected _validationError$!: Observable<IDataSourceValidationError>; | ||||
|   protected _notifyMessage$!: Observable<IDataSourceNotifyMessage>; | ||||
|   protected _commandStarted$!: Observable<IDataSourceCommandStarted>; | ||||
| 
 | ||||
|   protected _criteria: IQueryCriteria = { | ||||
|     filters: [], | ||||
|     aggregates: [], | ||||
|     groups: [], | ||||
|     sorts: [] | ||||
|   }; | ||||
| 
 | ||||
|   get data$() { | ||||
|     if (!this._data$) | ||||
|       this._data$ = this._dataSubject.asObservable(); | ||||
| 
 | ||||
|     return this._data$; | ||||
|   } | ||||
| 
 | ||||
|   get loading$() { | ||||
|     if (!this._loading$) | ||||
|       this._loading$ = this._loadingSubject.asObservable(); | ||||
| 
 | ||||
|     return this._loading$; | ||||
|   } | ||||
| 
 | ||||
|   get validationError$() { | ||||
|     if (!this._validationError$) | ||||
|       this._validationError$ = this._validationSubject.asObservable(); | ||||
| 
 | ||||
|     return this._validationError$; | ||||
|   } | ||||
| 
 | ||||
|   get commandStarted$() { | ||||
|     if (!this._commandStarted$) | ||||
|       this._commandStarted$ = this._commandStartedSubject.asObservable(); | ||||
| 
 | ||||
|     return this._commandStarted$; | ||||
|   } | ||||
| 
 | ||||
|   get notifyMessage$() { | ||||
|     if (!this._notifyMessage$) | ||||
|       this._notifyMessage$ = this._notifyMessageSubject.asObservable(); | ||||
| 
 | ||||
|     return this._notifyMessage$; | ||||
|   } | ||||
| 
 | ||||
|   constructor(public options: IDataSourceOptions<TQuery, TModel>) { | ||||
|     this._initCriteria(); | ||||
|   } | ||||
| 
 | ||||
|   clear() { | ||||
|     this.data = undefined; | ||||
|     this._dataSubject.next(null); | ||||
|   } | ||||
| 
 | ||||
|   updateData(value: IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>) { | ||||
|     this.data = value; | ||||
|     this._dataSubject.next(this.data); | ||||
|   } | ||||
| 
 | ||||
|   replaceDataWithArray(items: TModel[]) { | ||||
|     this.data = { | ||||
|       totalRecords: items.length, | ||||
|       numberOfPages: undefined, | ||||
|       groups: undefined, | ||||
|       aggregates: undefined, | ||||
|       data: items | ||||
|     }; | ||||
|     this._dataSubject.next(this.data); | ||||
|   } | ||||
| 
 | ||||
|   replaceDataWithSingle(item: TModel) { | ||||
|     this.data = { | ||||
|       totalRecords: 1, | ||||
|       numberOfPages: undefined, | ||||
|       groups: undefined, | ||||
|       aggregates: undefined, | ||||
|       data: [item] | ||||
|     }; | ||||
|     this._dataSubject.next(this.data); | ||||
|   } | ||||
| 
 | ||||
|   protected _initCriteria() { | ||||
|     if (!this.options.defaultCriteria) | ||||
|       return; | ||||
| 
 | ||||
|     const copy: IQueryCriteria = JSON.parse(JSON.stringify(this.options.defaultCriteria)); | ||||
|     this._criteria.page = copy.page || this._criteria.page; | ||||
|     this._criteria.pageSize = copy.pageSize || this._criteria.pageSize; | ||||
|     this._criteria.filters = copy.filters || this._criteria.filters; | ||||
|     this._criteria.groups = copy.groups || this._criteria.groups; | ||||
|     this._criteria.aggregates = copy.aggregates || this._criteria.aggregates; | ||||
|     this._criteria.sorts = copy.sorts || this._criteria.sorts; | ||||
|   } | ||||
| 
 | ||||
|   resolveIdField(model: TModel): TModel[keyof TModel] { | ||||
|     if (this.options.idField) { | ||||
|       return model[this.options.idField]; | ||||
|     } | ||||
| 
 | ||||
|     if (this.options.resolveIdField) { | ||||
|       return this.options.resolveIdField(model); | ||||
|     } | ||||
| 
 | ||||
|     throw new Error("Must specify an id field or supply a method to resolve the id field."); | ||||
|   } | ||||
| 
 | ||||
|   resolveCommandModelByName<T extends any>(event: IResolveCommandModelEvent<TModel>) : Observable<T> { | ||||
|     if (!this.options.transport.commands.hasOwnProperty(event.command)) | ||||
|       return throwError(() => <IDataSourceErrorMessage>{ | ||||
|         type: 'message', | ||||
|         message: `command with name ${event.command} not found` | ||||
|       }); | ||||
| 
 | ||||
|     const commandOptions = this.options.transport.commands[event.command]; | ||||
|     if (commandOptions.resolveCommandModel) | ||||
|       return commandOptions.resolveCommandModel(event); | ||||
| 
 | ||||
|     const noResolveMethod: any = event.model || {}; | ||||
|     return of(noResolveMethod); | ||||
|   } | ||||
| 
 | ||||
|   executeCommandByName<TCommand extends ICommand, TResult>(name: string, command: TCommand) : Observable<TResult> { | ||||
|     if (!this.options.transport.commands.hasOwnProperty(name)) | ||||
|       return throwError(() => `command with name ${name} not found`); | ||||
| 
 | ||||
|     this._commandStartedSubject.next({ | ||||
|       name: name, command: command | ||||
|     }); | ||||
| 
 | ||||
|     return this.options.transport.commands[name].adapter.handle(command).pipe( | ||||
|       map(t => { | ||||
|         this._notifyMessageSubject.next({ | ||||
|           type: 'success', | ||||
|           message: 'COMMAND_EXECUTED_SUCCESSFULLY', | ||||
|           messageParams: { | ||||
|             command: name | ||||
|           } | ||||
|         }); | ||||
|         return t; | ||||
|       }), | ||||
|       catchError((err: IDataSourceError) => { | ||||
|         if (err.type == 'message') | ||||
|           this._notifyMessageSubject.next({ | ||||
|             type: 'error', | ||||
|             message: (err as IDataSourceErrorMessage).message | ||||
|           }); | ||||
|         else if(err.type == 'validation') | ||||
|           this._validationSubject.next(err as IDataSourceValidationError); | ||||
| 
 | ||||
|         return throwError(() => err); | ||||
|       }) | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   private _query() : Observable<IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>> { | ||||
|     return new Observable<IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>>((o: Observer<IQueryExecutionResult<TModel> & IQueryExecutionGroupResult<TModel>>) => { | ||||
|       this._loadingSubject.next(true); | ||||
|       this.options.transport.query.adapter.handle(this._criteria as TQuery) | ||||
|         .pipe( | ||||
|           finalize(() => { | ||||
|             o.complete(); | ||||
|             this._loadingSubject.next(false); | ||||
|           }) | ||||
|         ) | ||||
|         .subscribe({ | ||||
|           next: (result) => | ||||
|           { | ||||
|             this.data = result; | ||||
|             o.next(result); | ||||
|             this._dataSubject.next(this.data); | ||||
|             this._notifyMessageSubject.next({ | ||||
|               message: 'NEW_DATA_READ_SUCCESSFULLY', | ||||
|               type: 'info' | ||||
|             }); | ||||
|           }, | ||||
|           error: (err) => { | ||||
|             o.error(err); | ||||
|             this._notifyMessageSubject.next({ | ||||
|               message: 'UNEXPECTED_ERROR_OCCURRED', | ||||
|               type: 'error' | ||||
|             }); | ||||
|           } | ||||
|         }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   query(query: TQuery) { | ||||
|     this._criteria.page = query.page === undefined ? this._criteria.page:query.page; | ||||
|     this._criteria.pageSize = query.pageSize === undefined ? this._criteria.pageSize: query.pageSize; | ||||
|     this._criteria.filters = query.filters || this._criteria.filters; | ||||
|     this._criteria.groups = query.groups || this._criteria.groups; | ||||
|     this._criteria.aggregates = query.aggregates || this._criteria.aggregates; | ||||
|     this._criteria.sorts = query.sorts || this._criteria.sorts; | ||||
|     return this.refresh(); | ||||
|   } | ||||
| 
 | ||||
|   executeQuery(query: TQuery): Observable<IQueryExecutionGroupResult<TModel>>{ | ||||
|     return this.options.transport.query.adapter.handle(query); | ||||
|   } | ||||
| 
 | ||||
|   refresh() { | ||||
|     return this._query() | ||||
|       .subscribe(); | ||||
|   } | ||||
| 
 | ||||
|   get sorts() { | ||||
|     return this._criteria.sorts ?? []; | ||||
|   } | ||||
| 
 | ||||
|   set sorts(value: ISort[]) { | ||||
|     this._criteria.sorts = value; | ||||
|     this.refresh(); | ||||
|   } | ||||
| 
 | ||||
|   get filters() { | ||||
|     return this._criteria.filters ?? []; | ||||
|   } | ||||
| 
 | ||||
|   set filters(value: IFilter[]) { | ||||
|     this._criteria.filters = value; | ||||
|     this.refresh(); | ||||
|   } | ||||
| 
 | ||||
|   get groups() { | ||||
|     return this._criteria.groups ?? []; | ||||
|   } | ||||
| 
 | ||||
|   set groups(value: IGroup[]) { | ||||
|     this._criteria.groups = value; | ||||
|     this.refresh(); | ||||
|   } | ||||
| 
 | ||||
|   get aggregates() { | ||||
|     return this._criteria.aggregates ?? []; | ||||
|   } | ||||
| 
 | ||||
|   set aggregates(value: IAggregate[]) { | ||||
|     this._criteria.aggregates = value; | ||||
|     this.refresh(); | ||||
|   } | ||||
| 
 | ||||
|   get pageSize() { | ||||
|     return this._criteria.pageSize ?? 25; | ||||
|   } | ||||
| 
 | ||||
|   set pageSize(value: number) { | ||||
|     this._criteria.pageSize = value; | ||||
|     this.refresh(); | ||||
|   } | ||||
| 
 | ||||
|   get page() { | ||||
|     return this._criteria.page ?? 0; | ||||
|   } | ||||
| 
 | ||||
|   set page(value: number) { | ||||
|     this._criteria.page = value; | ||||
|     this.refresh(); | ||||
|   } | ||||
| } | ||||
| @ -1,95 +0,0 @@ | ||||
| export interface IAggregate { | ||||
|     path: string; | ||||
|     type: string; | ||||
| } | ||||
| 
 | ||||
| export interface ISort { | ||||
|     path: string; | ||||
|     ascending?: boolean; | ||||
| } | ||||
| 
 | ||||
| export interface ISimpleFilter extends IFilter { | ||||
|     path: string; | ||||
|     value: any; | ||||
| } | ||||
| 
 | ||||
| export interface IQueryResult<TModel> { | ||||
|     aggregates?: IAggregateResult[]; | ||||
|     data?: TModel[]; | ||||
| } | ||||
| 
 | ||||
| export interface IQueryExecutionResultPaging { | ||||
|     totalRecords: number; | ||||
|     numberOfPages?: number; | ||||
| } | ||||
| 
 | ||||
| export interface IQueryExecutionResult<TRecord> extends IQueryResult<TRecord>, IQueryExecutionResultPaging { | ||||
| } | ||||
| 
 | ||||
| export interface IQueryExecutionGroupResult<TModel> extends IQueryExecutionResult<TModel> { | ||||
|     groups: IGroupQueryResult<TModel>[]; | ||||
| } | ||||
| 
 | ||||
| export interface IQueryCriteria { | ||||
|     page?: number; | ||||
|     pageSize?: number; | ||||
|     sorts?: ISort[]; | ||||
|     groups?: IGroup[]; | ||||
|     aggregates?: IAggregate[]; | ||||
|     filters?: IFilter[]; | ||||
| } | ||||
| 
 | ||||
| export interface IGroupQueryResult<TModel> extends IQueryResult<TModel> { | ||||
|     groupPath: string; | ||||
|     groupValue: any; | ||||
|     hasSubGroups: boolean; | ||||
|     subGroups?: IGroupQueryResult<TModel>[]; | ||||
| } | ||||
| 
 | ||||
| export interface IGroup { | ||||
|     path: string; | ||||
|     ascending?: boolean; | ||||
| } | ||||
| 
 | ||||
| export interface IFilter { | ||||
|     type: string; | ||||
|     and?: boolean; | ||||
| } | ||||
| 
 | ||||
| export interface IAggregateResult { | ||||
|     path: string; | ||||
|     type: string; | ||||
|     value: any; | ||||
| } | ||||
| 
 | ||||
| export interface ICompositeFilter extends IFilter { | ||||
|     filters: IFilter[]; | ||||
| } | ||||
| 
 | ||||
| export const enum AggregateType { | ||||
|     COUNT = 'Count', | ||||
|     SUM = 'Sum', | ||||
|     AVG = 'Avg', | ||||
|     LONGCOUNT = 'LongCount', | ||||
|     MIN = 'Min', | ||||
|     MAX = 'Max', | ||||
|     FIRST = 'First', | ||||
|     FIRSTORDEFAULT = 'FirstOrDefault', | ||||
|     LAST = 'Last', | ||||
|     LASTORDEFAULT = 'LastOrDefault' | ||||
| } | ||||
| 
 | ||||
| export const enum FilterType { | ||||
|     EQUAL = 'Equal', | ||||
|     CONTAINS = 'Contains', | ||||
|     STARTSWITH = 'StartsWith', | ||||
|     ENDSWITH = 'EndsWith', | ||||
|     COMPOSITE = 'Composite', | ||||
|     NOTEQUAL = 'NotEqual', | ||||
|     GREATERTHAN = 'GreaterThan', | ||||
|     LESSTHANOREQUAL = 'LessThanOrEqual',  | ||||
|     GREATERTHANOREQUAL = 'GreaterThanOrEqual', | ||||
|     LESSTHAN ='LessThan', | ||||
|     IN = 'In', | ||||
|     NOTIN = 'NotIn' | ||||
| } | ||||
| @ -2,18 +2,7 @@ | ||||
|  * Public API Surface of data | ||||
|  */ | ||||
| 
 | ||||
| export * from './lib/models'; | ||||
| export * from './lib/DataSource'; | ||||
| export * from './lib/IAdvanceQueryAdapter'; | ||||
| export * from './lib/ICommandAdapter'; | ||||
| export * from './lib/IDataSource'; | ||||
| export * from './lib/IDataSourceOptions'; | ||||
| export * from './lib/IDataSourceQueryAdapterOptions'; | ||||
| export * from './lib/IQueryAdapter'; | ||||
| export * from './lib/IResolveCommandModelEvent'; | ||||
| export * from './lib/IDataSourceCommandAdapterOptions'; | ||||
| export * from './lib/IDataSourceValidationError'; | ||||
| export * from './lib/IDataSourceError'; | ||||
| export * from './lib/IDataSourceErrorMessage'; | ||||
| export * from './lib/IDataSourceNotifyMessage'; | ||||
| 
 | ||||
| export * from './lib/abstractions/data-source.abstraction'; | ||||
| export * from './lib/abstractions/query.abstraction'; | ||||
| export * from './lib/abstractions/command.abstraction'; | ||||
| export * from './lib/data-source'; | ||||
|  | ||||
| @ -1,26 +1,15 @@ | ||||
| /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ | ||||
| /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ | ||||
| { | ||||
|   "extends": "../../tsconfig.json", | ||||
|   "compilerOptions": { | ||||
|     "outDir": "../../../out-tsc/lib", | ||||
|     "target": "es2015", | ||||
|     "outDir": "../../out-tsc/lib", | ||||
|     "declaration": true, | ||||
|     "declarationMap": true, | ||||
|     "inlineSources": true, | ||||
|     "types": [], | ||||
|     "lib": [ | ||||
|       "dom", | ||||
|       "es2018" | ||||
|     ] | ||||
|   }, | ||||
|   "angularCompilerOptions": { | ||||
|     "annotateForClosureCompiler": true, | ||||
|     "skipTemplateCodegen": true, | ||||
|     "strictMetadataEmit": true, | ||||
|     "fullTemplateTypeCheck": true, | ||||
|     "strictInjectionParameters": true, | ||||
|     "enableResourceInlining": true | ||||
|     "types": [] | ||||
|   }, | ||||
|   "exclude": [ | ||||
|     "src/test.ts", | ||||
|     "**/*.spec.ts" | ||||
|   ] | ||||
| } | ||||
|  | ||||
							
								
								
									
										11
									
								
								projects/data/tsconfig.lib.prod.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								projects/data/tsconfig.lib.prod.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ | ||||
| /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ | ||||
| { | ||||
|   "extends": "./tsconfig.lib.json", | ||||
|   "compilerOptions": { | ||||
|     "declarationMap": false | ||||
|   }, | ||||
|   "angularCompilerOptions": { | ||||
|     "compilationMode": "partial" | ||||
|   } | ||||
| } | ||||
| @ -1,15 +1,13 @@ | ||||
| /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ | ||||
| /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ | ||||
| { | ||||
|   "extends": "../../tsconfig.json", | ||||
|   "compilerOptions": { | ||||
|     "outDir": "../../../out-tsc/spec", | ||||
|     "outDir": "../../out-tsc/spec", | ||||
|     "types": [ | ||||
|       "jasmine", | ||||
|       "node" | ||||
|       "jasmine" | ||||
|     ] | ||||
|   }, | ||||
|   "files": [ | ||||
|     "src/test.ts" | ||||
|   ], | ||||
|   "include": [ | ||||
|     "**/*.spec.ts", | ||||
|     "**/*.d.ts" | ||||
|  | ||||
| @ -1,17 +0,0 @@ | ||||
| { | ||||
|   "extends": "../../tslint.json", | ||||
|   "rules": { | ||||
|     "directive-selector": [ | ||||
|       true, | ||||
|       "attribute", | ||||
|       "lib", | ||||
|       "camelCase" | ||||
|     ], | ||||
|     "component-selector": [ | ||||
|       true, | ||||
|       "element", | ||||
|       "lib", | ||||
|       "kebab-case" | ||||
|     ] | ||||
|   } | ||||
| } | ||||
| @ -1,6 +0,0 @@ | ||||
| <h1>{{ title }}</h1> | ||||
| <h4>{{ type }}</h4> | ||||
| <div> | ||||
|   {{ message }} | ||||
| </div> | ||||
| <button (click)="onDoSomething()">Do something</button> | ||||
| @ -1,145 +0,0 @@ | ||||
| import {Component, OnInit} from '@angular/core'; | ||||
| import {IDataSourceNotifyMessage} from '../../projects/data/src/lib/IDataSourceNotifyMessage'; | ||||
| import { | ||||
|   DataSource, | ||||
|   IDataSource, | ||||
|   IDataSourceCommandAdapterOptions, | ||||
|   IDataSourceQueryAdapterOptions, | ||||
|   IDataSourceTransportOptions, | ||||
|   IDataSourceValidationError, | ||||
|   IQueryCriteria, | ||||
|   IQueryExecutionGroupResult, | ||||
|   IQueryExecutionResult | ||||
| } from '@openharbor/data'; | ||||
| import {HttpClient} from '@angular/common/http'; | ||||
| import {of, throwError} from 'rxjs'; | ||||
| 
 | ||||
| export interface MyModel { | ||||
|     id: number; | ||||
|     name: string; | ||||
| } | ||||
| 
 | ||||
| @Component({ | ||||
|     selector: 'app-root', | ||||
|     templateUrl: './app.component.html', | ||||
|     styleUrls: ['./app.component.css'] | ||||
| }) | ||||
| 
 | ||||
| export class AppComponent implements OnInit { | ||||
|     title = 'data'; | ||||
|     message: string = ''; | ||||
|     type: string = ''; | ||||
| 
 | ||||
|     dataSource: IDataSource<any>; | ||||
|     createCommand: IDataSourceCommandAdapterOptions<MyModel>; | ||||
|     test:any; | ||||
|     public constructor(private http: HttpClient) { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     ngOnInit(): void { | ||||
|         const keyResolver = (m: MyModel) => m.id; | ||||
|         let route = 'http://localhost:9999'; | ||||
| 
 | ||||
|         const query: IDataSourceQueryAdapterOptions<MyModel> = { | ||||
|             adapter: { | ||||
|                 handle: (criteria: IQueryCriteria) => { | ||||
|                     const queryRoute = `${route}/read`; | ||||
|                     return this.http.post<IQueryExecutionResult<MyModel> & IQueryExecutionGroupResult<MyModel>>(queryRoute, criteria); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         this.createCommand = { | ||||
|             adapter: { | ||||
|                 handle: (command: MyModel) => { | ||||
|                     return of(command); | ||||
|                     //return this.http.post<MyModel>(route, command);
 | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         const updateCommand: IDataSourceCommandAdapterOptions<MyModel> = { | ||||
|             adapter: { | ||||
|                 handle: (command: MyModel) => { | ||||
|                     const key = keyResolver(command); | ||||
|                     const updateRoute = `${route}/${encodeURIComponent(key as any)}`; | ||||
|                     return throwError(<IDataSourceValidationError>{ | ||||
|                         type: 'validation', | ||||
|                         errors: { | ||||
|                             'name': [ | ||||
|                                 'David is not unique' | ||||
|                             ] | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         const deleteCommand: IDataSourceCommandAdapterOptions<MyModel> = { | ||||
|             adapter: { | ||||
|                 handle: (command: MyModel) => { | ||||
|                     const key = keyResolver(command); | ||||
|                     const updateRoute = `${route}/${encodeURIComponent(key as any)}`; | ||||
|                     return of(command); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         const transportOptions: IDataSourceTransportOptions<MyModel> = { | ||||
|             query: query, | ||||
|             commands: { | ||||
|                 'create': this.createCommand, | ||||
|                 'update': updateCommand, | ||||
|                 'delete': deleteCommand | ||||
|             } | ||||
|         }; | ||||
|         this.dataSource = new DataSource<MyModel>({ | ||||
|             transport: transportOptions, | ||||
|             defaultCriteria: { | ||||
|                 page: 1, | ||||
|                 pageSize: 5, | ||||
|                 groups: [ | ||||
|                     { path: 'name' } | ||||
|                 ] | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         this.dataSource.notifyMessage$.subscribe((notifyMessage) => { | ||||
|             this.handleNotification(notifyMessage); | ||||
|         }); | ||||
| 
 | ||||
|         this.dataSource.validationError$.subscribe((t) => { | ||||
| 
 | ||||
|             let message = ''; | ||||
|             for (var key in t.errors) | ||||
|                 t.errors[key].forEach(error => message += `\n${error}`); | ||||
| 
 | ||||
|             this.handleNotification({ | ||||
|                 type: 'error', | ||||
|                 message: message | ||||
|             }); | ||||
|         }); | ||||
| 
 | ||||
|         this.test = this.dataSource.query({ | ||||
|             page:null, | ||||
|             pageSize: null, | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     handleNotification(notification: IDataSourceNotifyMessage) { | ||||
|         this.message = notification.message; | ||||
|     } | ||||
| 
 | ||||
|     onDoSomething() { | ||||
|         this.dataSource.executeCommandByName('create', {}).subscribe(() => { | ||||
|             console.log('hey we did it!'); | ||||
|         }); | ||||
|         this.dataSource.executeCommandByName('update', {}).subscribe(() => { | ||||
| 
 | ||||
|         }); | ||||
|         //this.dataSource.refresh();
 | ||||
| 
 | ||||
|         console.log(this.test); | ||||
|     } | ||||
| } | ||||
| @ -1,18 +0,0 @@ | ||||
| import { BrowserModule } from '@angular/platform-browser'; | ||||
| import { NgModule } from '@angular/core'; | ||||
| 
 | ||||
| import { AppComponent } from './app.component'; | ||||
| import { HttpClientModule } from '@angular/common/http'; | ||||
| 
 | ||||
| @NgModule({ | ||||
|   declarations: [ | ||||
|     AppComponent | ||||
|   ], | ||||
|   imports: [ | ||||
|     HttpClientModule, | ||||
|     BrowserModule | ||||
|   ], | ||||
|   providers: [], | ||||
|   bootstrap: [AppComponent] | ||||
| }) | ||||
| export class AppModule { } | ||||
| @ -1,3 +0,0 @@ | ||||
| export const environment = { | ||||
|   production: true | ||||
| }; | ||||
| @ -1,16 +0,0 @@ | ||||
| // This file can be replaced during build by using the `fileReplacements` array.
 | ||||
| // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
 | ||||
| // The list of file replacements can be found in `angular.json`.
 | ||||
| 
 | ||||
| export const environment = { | ||||
|   production: false | ||||
| }; | ||||
| 
 | ||||
| /* | ||||
|  * For easier debugging in development mode, you can import the following file | ||||
|  * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. | ||||
|  * | ||||
|  * This import should be commented out in production mode because it will have a negative impact | ||||
|  * on performance if an error is thrown. | ||||
|  */ | ||||
| // import 'zone.js/dist/zone-error';  // Included with Angular CLI.
 | ||||
							
								
								
									
										
											BIN
										
									
								
								src/favicon.ico
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/favicon.ico
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 948 B | 
| @ -1,13 +0,0 @@ | ||||
| <!doctype html> | ||||
| <html lang="en"> | ||||
| <head> | ||||
|   <meta charset="utf-8"> | ||||
|   <title>Data</title> | ||||
|   <base href="/"> | ||||
|   <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||
|   <link rel="icon" type="image/x-icon" href="favicon.ico"> | ||||
| </head> | ||||
| <body> | ||||
|   <app-root></app-root> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										12
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/main.ts
									
									
									
									
									
								
							| @ -1,12 +0,0 @@ | ||||
| import { enableProdMode } from '@angular/core'; | ||||
| import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; | ||||
| 
 | ||||
| import { AppModule } from './app/app.module'; | ||||
| import { environment } from './environments/environment'; | ||||
| 
 | ||||
| if (environment.production) { | ||||
|   enableProdMode(); | ||||
| } | ||||
| 
 | ||||
| platformBrowserDynamic().bootstrapModule(AppModule) | ||||
|   .catch(err => console.error(err)); | ||||
| @ -1,63 +0,0 @@ | ||||
| /** | ||||
|  * This file includes polyfills needed by Angular and is loaded before the app. | ||||
|  * You can add your own extra polyfills to this file. | ||||
|  * | ||||
|  * This file is divided into 2 sections: | ||||
|  *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. | ||||
|  *   2. Application imports. Files imported after ZoneJS that should be loaded before your main | ||||
|  *      file. | ||||
|  * | ||||
|  * The current setup is for so-called "evergreen" browsers; the last versions of browsers that | ||||
|  * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), | ||||
|  * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. | ||||
|  * | ||||
|  * Learn more in https://angular.io/guide/browser-support
 | ||||
|  */ | ||||
| 
 | ||||
| /*************************************************************************************************** | ||||
|  * BROWSER POLYFILLS | ||||
|  */ | ||||
| 
 | ||||
| /** IE10 and IE11 requires the following for NgClass support on SVG elements */ | ||||
| // import 'classlist.js';  // Run `npm install --save classlist.js`.
 | ||||
| 
 | ||||
| /** | ||||
|  * Web Animations `@angular/platform-browser/animations` | ||||
|  * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. | ||||
|  * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). | ||||
|  */ | ||||
| // import 'web-animations-js';  // Run `npm install --save web-animations-js`.
 | ||||
| 
 | ||||
| /** | ||||
|  * By default, zone.js will patch all possible macroTask and DomEvents | ||||
|  * user can disable parts of macroTask/DomEvents patch by setting following flags | ||||
|  * because those flags need to be set before `zone.js` being loaded, and webpack | ||||
|  * will put import in the top of bundle, so user need to create a separate file | ||||
|  * in this directory (for example: zone-flags.ts), and put the following flags | ||||
|  * into that file, and then add the following code before importing zone.js. | ||||
|  * import './zone-flags.ts'; | ||||
|  * | ||||
|  * The flags allowed in zone-flags.ts are listed here. | ||||
|  * | ||||
|  * The following flags will work for all browsers. | ||||
|  * | ||||
|  * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
 | ||||
|  * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
 | ||||
|  * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
 | ||||
|  * | ||||
|  *  in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js | ||||
|  *  with the following flag, it will bypass `zone.js` patch for IE/Edge | ||||
|  * | ||||
|  *  (window as any).__Zone_enable_cross_context_check = true; | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| /*************************************************************************************************** | ||||
|  * Zone JS is required by default for Angular itself. | ||||
|  */ | ||||
| import 'zone.js/dist/zone';  // Included with Angular CLI.
 | ||||
| 
 | ||||
| 
 | ||||
| /*************************************************************************************************** | ||||
|  * APPLICATION IMPORTS | ||||
|  */ | ||||
| @ -1 +0,0 @@ | ||||
| /* You can add global styles to this file, and also import other style files */ | ||||
							
								
								
									
										20
									
								
								src/test.ts
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/test.ts
									
									
									
									
									
								
							| @ -1,20 +0,0 @@ | ||||
| // This file is required by karma.conf.js and loads recursively all the .spec and framework files
 | ||||
| 
 | ||||
| import 'zone.js/dist/zone-testing'; | ||||
| import { getTestBed } from '@angular/core/testing'; | ||||
| import { | ||||
|   BrowserDynamicTestingModule, | ||||
|   platformBrowserDynamicTesting | ||||
| } from '@angular/platform-browser-dynamic/testing'; | ||||
| 
 | ||||
| declare const require: any; | ||||
| 
 | ||||
| // First, initialize the Angular testing environment.
 | ||||
| getTestBed().initTestEnvironment( | ||||
|   BrowserDynamicTestingModule, | ||||
|   platformBrowserDynamicTesting() | ||||
| ); | ||||
| // Then we find all the tests.
 | ||||
| const context = require.context('./', true, /\.spec\.ts$/); | ||||
| // And load the modules.
 | ||||
| context.keys().map(context); | ||||
| @ -1,18 +0,0 @@ | ||||
| { | ||||
|   "extends": "./tsconfig.json", | ||||
|   "compilerOptions": { | ||||
|     "outDir": "./out-tsc/app", | ||||
|     "types": [] | ||||
|   }, | ||||
|   "files": [ | ||||
|     "src/main.ts", | ||||
|     "src/polyfills.ts" | ||||
|   ], | ||||
|   "include": [ | ||||
|     "src/**/*.ts" | ||||
|   ], | ||||
|   "exclude": [ | ||||
|     "src/test.ts", | ||||
|     "src/**/*.spec.ts" | ||||
|   ] | ||||
| } | ||||
| @ -1,31 +1,38 @@ | ||||
| /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ | ||||
| /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ | ||||
| { | ||||
|   "compileOnSave": false, | ||||
|   "compilerOptions": { | ||||
|     "baseUrl": "./", | ||||
|     "outDir": "./dist/out-tsc", | ||||
|     "sourceMap": true, | ||||
|     "declaration": false, | ||||
|     "downlevelIteration": true, | ||||
|     "experimentalDecorators": true, | ||||
|     "module": "esnext", | ||||
|     "moduleResolution": "node", | ||||
|     "importHelpers": true, | ||||
|     "target": "es2015", | ||||
|     "typeRoots": [ | ||||
|       "node_modules/@types" | ||||
|     ], | ||||
|     "lib": [ | ||||
|       "es2018", | ||||
|       "dom" | ||||
|     ], | ||||
|     "paths": { | ||||
|       "@openharbor/data": [ | ||||
|         "./projects/data/src/public-api" | ||||
|       ], | ||||
|     } | ||||
|       ] | ||||
|     }, | ||||
|     "outDir": "./dist/out-tsc", | ||||
|     "strict": true, | ||||
|     "noImplicitOverride": true, | ||||
|     "noPropertyAccessFromIndexSignature": true, | ||||
|     "noImplicitReturns": true, | ||||
|     "noFallthroughCasesInSwitch": true, | ||||
|     "skipLibCheck": true, | ||||
|     "esModuleInterop": true, | ||||
|     "sourceMap": true, | ||||
|     "declaration": false, | ||||
|     "experimentalDecorators": true, | ||||
|     "moduleResolution": "bundler", | ||||
|     "importHelpers": true, | ||||
|     "target": "ES2022", | ||||
|     "module": "ES2022", | ||||
|     "useDefineForClassFields": false, | ||||
|     "lib": [ | ||||
|       "ES2022", | ||||
|       "dom" | ||||
|     ] | ||||
|   }, | ||||
|   "angularCompilerOptions": { | ||||
|     "fullTemplateTypeCheck": true, | ||||
|     "strictInjectionParameters": true | ||||
|     "enableI18nLegacyMessageIdFormat": false, | ||||
|     "strictInjectionParameters": true, | ||||
|     "strictInputAccessModifiers": true, | ||||
|     "strictTemplates": true | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -1,18 +0,0 @@ | ||||
| { | ||||
|   "extends": "./tsconfig.json", | ||||
|   "compilerOptions": { | ||||
|     "outDir": "./out-tsc/spec", | ||||
|     "types": [ | ||||
|       "jasmine", | ||||
|       "node" | ||||
|     ] | ||||
|   }, | ||||
|   "files": [ | ||||
|     "src/test.ts", | ||||
|     "src/polyfills.ts" | ||||
|   ], | ||||
|   "include": [ | ||||
|     "src/**/*.spec.ts", | ||||
|     "src/**/*.d.ts" | ||||
|   ] | ||||
| } | ||||
							
								
								
									
										92
									
								
								tslint.json
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								tslint.json
									
									
									
									
									
								
							| @ -1,92 +0,0 @@ | ||||
| { | ||||
|   "extends": "tslint:recommended", | ||||
|   "rules": { | ||||
|     "array-type": false, | ||||
|     "arrow-parens": false, | ||||
|     "deprecation": { | ||||
|       "severity": "warning" | ||||
|     }, | ||||
|     "component-class-suffix": true, | ||||
|     "contextual-lifecycle": true, | ||||
|     "directive-class-suffix": true, | ||||
|     "directive-selector": [ | ||||
|       true, | ||||
|       "attribute", | ||||
|       "app", | ||||
|       "camelCase" | ||||
|     ], | ||||
|     "component-selector": [ | ||||
|       true, | ||||
|       "element", | ||||
|       "app", | ||||
|       "kebab-case" | ||||
|     ], | ||||
|     "import-blacklist": [ | ||||
|       true, | ||||
|       "rxjs/Rx" | ||||
|     ], | ||||
|     "interface-name": false, | ||||
|     "max-classes-per-file": false, | ||||
|     "max-line-length": [ | ||||
|       true, | ||||
|       140 | ||||
|     ], | ||||
|     "member-access": false, | ||||
|     "member-ordering": [ | ||||
|       true, | ||||
|       { | ||||
|         "order": [ | ||||
|           "static-field", | ||||
|           "instance-field", | ||||
|           "static-method", | ||||
|           "instance-method" | ||||
|         ] | ||||
|       } | ||||
|     ], | ||||
|     "no-consecutive-blank-lines": false, | ||||
|     "no-console": [ | ||||
|       true, | ||||
|       "debug", | ||||
|       "info", | ||||
|       "time", | ||||
|       "timeEnd", | ||||
|       "trace" | ||||
|     ], | ||||
|     "no-empty": false, | ||||
|     "no-inferrable-types": [ | ||||
|       true, | ||||
|       "ignore-params" | ||||
|     ], | ||||
|     "no-non-null-assertion": true, | ||||
|     "no-redundant-jsdoc": true, | ||||
|     "no-switch-case-fall-through": true, | ||||
|     "no-use-before-declare": true, | ||||
|     "no-var-requires": false, | ||||
|     "object-literal-key-quotes": [ | ||||
|       true, | ||||
|       "as-needed" | ||||
|     ], | ||||
|     "object-literal-sort-keys": false, | ||||
|     "ordered-imports": false, | ||||
|     "quotemark": [ | ||||
|       true, | ||||
|       "single" | ||||
|     ], | ||||
|     "trailing-comma": false, | ||||
|     "no-conflicting-lifecycle": true, | ||||
|     "no-host-metadata-property": true, | ||||
|     "no-input-rename": true, | ||||
|     "no-inputs-metadata-property": true, | ||||
|     "no-output-native": true, | ||||
|     "no-output-on-prefix": true, | ||||
|     "no-output-rename": true, | ||||
|     "no-outputs-metadata-property": true, | ||||
|     "template-banana-in-box": true, | ||||
|     "template-no-negated-async": true, | ||||
|     "use-lifecycle-interface": true, | ||||
|     "use-pipe-transform-interface": true | ||||
|   }, | ||||
|   "rulesDirectory": [ | ||||
|     "codelyzer" | ||||
|   ] | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user