ing
This commit is contained in:
commit
bc3f80b726
13
.editorconfig
Normal file
13
.editorconfig
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# Editor configuration, see http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
39
.gitignore
vendored
Normal file
39
.gitignore
vendored
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# compiled output
|
||||||
|
/dist
|
||||||
|
/tmp
|
||||||
|
/out-tsc
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
/.idea
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# IDE - VSCode
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
|
||||||
|
# misc
|
||||||
|
/.sass-cache
|
||||||
|
/connect.lock
|
||||||
|
/coverage
|
||||||
|
/libpeerconnection.log
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
testem.log
|
||||||
|
/typings
|
||||||
|
|
||||||
|
# System Files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
27
README.md
Normal file
27
README.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# LoaferNg
|
||||||
|
|
||||||
|
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.0.3.
|
||||||
|
|
||||||
|
## Development server
|
||||||
|
|
||||||
|
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||||
|
|
||||||
|
## Code scaffolding
|
||||||
|
|
||||||
|
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
|
||||||
|
|
||||||
|
## Running unit tests
|
||||||
|
|
||||||
|
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
||||||
|
|
||||||
|
## Running end-to-end tests
|
||||||
|
|
||||||
|
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
|
||||||
|
|
||||||
|
## 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).
|
241
angular.json
Normal file
241
angular.json
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
{
|
||||||
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
|
"version": 1,
|
||||||
|
"newProjectRoot": "projects",
|
||||||
|
"projects": {
|
||||||
|
"example": {
|
||||||
|
"root": "example",
|
||||||
|
"projectType": "application",
|
||||||
|
"prefix": "app",
|
||||||
|
"schematics": {},
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-angular:browser",
|
||||||
|
"options": {
|
||||||
|
"outputPath": "dist/example",
|
||||||
|
"index": "example/index.html",
|
||||||
|
"main": "example/main.ts",
|
||||||
|
"polyfills": "example/polyfills.ts",
|
||||||
|
"tsConfig": "example/tsconfig.app.json",
|
||||||
|
"assets": [
|
||||||
|
"example/favicon.ico",
|
||||||
|
"example/assets"
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"example/styles.css"
|
||||||
|
],
|
||||||
|
"scripts": []
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"fileReplacements": [
|
||||||
|
{
|
||||||
|
"replace": "example/environments/environment.ts",
|
||||||
|
"with": "example/environments/environment.prod.ts"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optimization": true,
|
||||||
|
"outputHashing": "all",
|
||||||
|
"sourceMap": false,
|
||||||
|
"extractCss": true,
|
||||||
|
"namedChunks": false,
|
||||||
|
"aot": true,
|
||||||
|
"extractLicenses": true,
|
||||||
|
"vendorChunk": false,
|
||||||
|
"buildOptimizer": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"builder": "@angular-devkit/build-angular:dev-server",
|
||||||
|
"options": {
|
||||||
|
"browserTarget": "example:build"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"browserTarget": "example:build:production"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extract-i18n": {
|
||||||
|
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||||
|
"options": {
|
||||||
|
"browserTarget": "example:build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"main": "example/test.ts",
|
||||||
|
"polyfills": "example/polyfills.ts",
|
||||||
|
"tsConfig": "example/tsconfig.spec.json",
|
||||||
|
"karmaConfig": "example/karma.conf.js",
|
||||||
|
"styles": [
|
||||||
|
"example/styles.css"
|
||||||
|
],
|
||||||
|
"scripts": [],
|
||||||
|
"assets": [
|
||||||
|
"example/favicon.ico",
|
||||||
|
"example/assets"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": [
|
||||||
|
"example/tsconfig.app.json",
|
||||||
|
"example/tsconfig.spec.json"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"**/node_modules/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example-e2e": {
|
||||||
|
"root": "e2e/",
|
||||||
|
"projectType": "application",
|
||||||
|
"architect": {
|
||||||
|
"e2e": {
|
||||||
|
"builder": "@angular-devkit/build-angular:protractor",
|
||||||
|
"options": {
|
||||||
|
"protractorConfig": "e2e/protractor.conf.js",
|
||||||
|
"devServerTarget": "example:serve"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": "e2e/tsconfig.e2e.json",
|
||||||
|
"exclude": [
|
||||||
|
"**/node_modules/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@loafer/ng-logger": {
|
||||||
|
"root": "projects/loafer/ng-logger",
|
||||||
|
"sourceRoot": "projects/loafer/ng-logger/src",
|
||||||
|
"projectType": "library",
|
||||||
|
"prefix": "lib",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": "projects/loafer/ng-logger/tsconfig.lib.json",
|
||||||
|
"project": "projects/loafer/ng-logger/ng-package.json"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"project": "projects/loafer/ng-logger/ng-package.prod.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"main": "projects/loafer/ng-logger/src/test.ts",
|
||||||
|
"tsConfig": "projects/loafer/ng-logger/tsconfig.spec.json",
|
||||||
|
"karmaConfig": "projects/loafer/ng-logger/karma.conf.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": [
|
||||||
|
"projects/loafer/ng-logger/tsconfig.lib.json",
|
||||||
|
"projects/loafer/ng-logger/tsconfig.spec.json"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"**/node_modules/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@loafer/ng-rest": {
|
||||||
|
"root": "projects/loafer/ng-rest",
|
||||||
|
"sourceRoot": "projects/loafer/ng-rest/src",
|
||||||
|
"projectType": "library",
|
||||||
|
"prefix": "lib",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": "projects/loafer/ng-rest/tsconfig.lib.json",
|
||||||
|
"project": "projects/loafer/ng-rest/ng-package.json"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"project": "projects/loafer/ng-rest/ng-package.prod.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"main": "projects/loafer/ng-rest/src/test.ts",
|
||||||
|
"tsConfig": "projects/loafer/ng-rest/tsconfig.spec.json",
|
||||||
|
"karmaConfig": "projects/loafer/ng-rest/karma.conf.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": [
|
||||||
|
"projects/loafer/ng-rest/tsconfig.lib.json",
|
||||||
|
"projects/loafer/ng-rest/tsconfig.spec.json"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"**/node_modules/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@loafer/ng-rpc": {
|
||||||
|
"root": "projects/loafer/ng-rpc",
|
||||||
|
"sourceRoot": "projects/loafer/ng-rpc/src",
|
||||||
|
"projectType": "library",
|
||||||
|
"prefix": "lib",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": "projects/loafer/ng-rpc/tsconfig.lib.json",
|
||||||
|
"project": "projects/loafer/ng-rpc/ng-package.json"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"project": "projects/loafer/ng-rpc/ng-package.prod.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"main": "projects/loafer/ng-rpc/src/test.ts",
|
||||||
|
"tsConfig": "projects/loafer/ng-rpc/tsconfig.spec.json",
|
||||||
|
"karmaConfig": "projects/loafer/ng-rpc/karma.conf.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
|
"options": {
|
||||||
|
"tsConfig": [
|
||||||
|
"projects/loafer/ng-rpc/tsconfig.lib.json",
|
||||||
|
"projects/loafer/ng-rpc/tsconfig.spec.json"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"**/node_modules/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultProject": "example"
|
||||||
|
}
|
28
e2e/protractor.conf.js
Normal file
28
e2e/protractor.conf.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// Protractor configuration file, see link for more information
|
||||||
|
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||||
|
|
||||||
|
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||||
|
|
||||||
|
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.e2e.json')
|
||||||
|
});
|
||||||
|
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||||
|
}
|
||||||
|
};
|
14
e2e/src/app.e2e-spec.ts
Normal file
14
e2e/src/app.e2e-spec.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { AppPage } from './app.po';
|
||||||
|
|
||||||
|
describe('workspace-project App', () => {
|
||||||
|
let page: AppPage;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
page = new AppPage();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display welcome message', () => {
|
||||||
|
page.navigateTo();
|
||||||
|
expect(page.getParagraphText()).toEqual('Welcome to app!');
|
||||||
|
});
|
||||||
|
});
|
11
e2e/src/app.po.ts
Normal file
11
e2e/src/app.po.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { browser, by, element } from 'protractor';
|
||||||
|
|
||||||
|
export class AppPage {
|
||||||
|
navigateTo() {
|
||||||
|
return browser.get('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
getParagraphText() {
|
||||||
|
return element(by.css('app-root h1')).getText();
|
||||||
|
}
|
||||||
|
}
|
13
e2e/tsconfig.e2e.json
Normal file
13
e2e/tsconfig.e2e.json
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../out-tsc/app",
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es5",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"jasminewd2",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
0
example/app/app.component.css
Normal file
0
example/app/app.component.css
Normal file
20
example/app/app.component.html
Normal file
20
example/app/app.component.html
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<!--The content below is only a placeholder and can be replaced.-->
|
||||||
|
<div style="text-align:center">
|
||||||
|
<h1>
|
||||||
|
Welcome to {{ title }}!
|
||||||
|
</h1>
|
||||||
|
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
|
||||||
|
</div>
|
||||||
|
<h2>Here are some links to help you start: </h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
27
example/app/app.component.spec.ts
Normal file
27
example/app/app.component.spec.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
describe('AppComponent', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
it('should create the app', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.debugElement.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
}));
|
||||||
|
it(`should have as title 'app'`, async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.debugElement.componentInstance;
|
||||||
|
expect(app.title).toEqual('app');
|
||||||
|
}));
|
||||||
|
it('should render title in a h1 tag', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
|
expect(compiled.querySelector('h1').textContent).toContain('Welcome to loafer-ng!');
|
||||||
|
}));
|
||||||
|
});
|
10
example/app/app.component.ts
Normal file
10
example/app/app.component.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.css']
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
title = 'app';
|
||||||
|
}
|
16
example/app/app.module.ts
Normal file
16
example/app/app.module.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
BrowserModule
|
||||||
|
],
|
||||||
|
providers: [],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
0
example/assets/.gitkeep
Normal file
0
example/assets/.gitkeep
Normal file
9
example/browserslist
Normal file
9
example/browserslist
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
|
||||||
|
# For additional information regarding the format and rule options, please see:
|
||||||
|
# https://github.com/browserslist/browserslist#queries
|
||||||
|
# For IE 9-11 support, please uncomment the last line of the file and adjust as needed
|
||||||
|
> 0.5%
|
||||||
|
last 2 versions
|
||||||
|
Firefox ESR
|
||||||
|
not dead
|
||||||
|
# IE 9-11
|
3
example/environments/environment.prod.ts
Normal file
3
example/environments/environment.prod.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export const environment = {
|
||||||
|
production: true
|
||||||
|
};
|
15
example/environments/environment.ts
Normal file
15
example/environments/environment.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// 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
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In development mode, to ignore zone related error stack frames such as
|
||||||
|
* `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can
|
||||||
|
* import the following file, but please comment it out in production mode
|
||||||
|
* because it will have performance impact when throw error
|
||||||
|
*/
|
||||||
|
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
|
BIN
example/favicon.ico
Normal file
BIN
example/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
14
example/index.html
Normal file
14
example/index.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>LoaferNg</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>
|
31
example/karma.conf.js
Normal file
31
example/karma.conf.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// 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'),
|
||||||
|
reports: ['html', 'lcovonly'],
|
||||||
|
fixWebpackSourcePaths: true
|
||||||
|
},
|
||||||
|
reporters: ['progress', 'kjhtml'],
|
||||||
|
port: 9876,
|
||||||
|
colors: true,
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
autoWatch: true,
|
||||||
|
browsers: ['Chrome'],
|
||||||
|
singleRun: false
|
||||||
|
});
|
||||||
|
};
|
12
example/main.ts
Normal file
12
example/main.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
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.log(err));
|
80
example/polyfills.ts
Normal file
80
example/polyfills.ts
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/**
|
||||||
|
* 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/docs/ts/latest/guide/browser-support.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************************
|
||||||
|
* BROWSER POLYFILLS
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
|
||||||
|
// import 'core-js/es6/symbol';
|
||||||
|
// import 'core-js/es6/object';
|
||||||
|
// import 'core-js/es6/function';
|
||||||
|
// import 'core-js/es6/parse-int';
|
||||||
|
// import 'core-js/es6/parse-float';
|
||||||
|
// import 'core-js/es6/number';
|
||||||
|
// import 'core-js/es6/math';
|
||||||
|
// import 'core-js/es6/string';
|
||||||
|
// import 'core-js/es6/date';
|
||||||
|
// import 'core-js/es6/array';
|
||||||
|
// import 'core-js/es6/regexp';
|
||||||
|
// import 'core-js/es6/map';
|
||||||
|
// import 'core-js/es6/weak-map';
|
||||||
|
// import 'core-js/es6/set';
|
||||||
|
|
||||||
|
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
|
||||||
|
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||||||
|
|
||||||
|
/** IE10 and IE11 requires the following for the Reflect API. */
|
||||||
|
// import 'core-js/es6/reflect';
|
||||||
|
|
||||||
|
|
||||||
|
/** Evergreen browsers require these. **/
|
||||||
|
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
|
||||||
|
import 'core-js/es7/reflect';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
// (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__BLACK_LISTED_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
example/styles.css
Normal file
1
example/styles.css
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/* You can add global styles to this file, and also import other style files */
|
20
example/test.ts
Normal file
20
example/test.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// 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);
|
12
example/tsconfig.app.json
Normal file
12
example/tsconfig.app.json
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../out-tsc/app",
|
||||||
|
"module": "es2015",
|
||||||
|
"types": []
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"src/test.ts",
|
||||||
|
"**/*.spec.ts"
|
||||||
|
]
|
||||||
|
}
|
19
example/tsconfig.spec.json
Normal file
19
example/tsconfig.spec.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../out-tsc/spec",
|
||||||
|
"module": "commonjs",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"test.ts",
|
||||||
|
"polyfills.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
17
example/tslint.json
Normal file
17
example/tslint.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"extends": "../tslint.json",
|
||||||
|
"rules": {
|
||||||
|
"directive-selector": [
|
||||||
|
true,
|
||||||
|
"attribute",
|
||||||
|
"app",
|
||||||
|
"camelCase"
|
||||||
|
],
|
||||||
|
"component-selector": [
|
||||||
|
true,
|
||||||
|
"element",
|
||||||
|
"app",
|
||||||
|
"kebab-case"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
11550
package-lock.json
generated
Normal file
11550
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
56
package.json
Normal file
56
package.json
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
{
|
||||||
|
"name": "loafer-ng",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"ng": "ng",
|
||||||
|
"start": "ng serve",
|
||||||
|
"build": "ng build",
|
||||||
|
"test": "ng test",
|
||||||
|
"lint": "ng lint",
|
||||||
|
"e2e": "ng e2e"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/common": "^6.0.2",
|
||||||
|
"@angular/core": "^6.0.2",
|
||||||
|
"@angular/compiler": "^6.0.2",
|
||||||
|
"@angular/animations": "^6.0.2",
|
||||||
|
"@angular/forms": "^6.0.2",
|
||||||
|
"@angular/http": "^6.0.2",
|
||||||
|
"@angular/platform-browser": "^6.0.2",
|
||||||
|
"@angular/platform-browser-dynamic": "^6.0.2",
|
||||||
|
"@angular/router": "^6.0.2",
|
||||||
|
"@loafer/core": "^0.0.1",
|
||||||
|
"@loafer/decorator": "^0.0.1",
|
||||||
|
"@ngrx/store": "^5.2.0",
|
||||||
|
"core-js": "^2.5.4",
|
||||||
|
"rxjs": "^6.0.0",
|
||||||
|
"rxjs-compat": "^6.0.0",
|
||||||
|
"zone.js": "^0.8.26"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular/compiler-cli": "^6.0.2",
|
||||||
|
"@angular-devkit/build-ng-packagr": "~0.6.3",
|
||||||
|
"@angular-devkit/build-angular": "~0.6.3",
|
||||||
|
"ng-packagr": "^3.0.0-rc.2",
|
||||||
|
"tsickle": ">=0.25.5",
|
||||||
|
"tslib": "^1.7.1",
|
||||||
|
"typescript": "~2.7.2",
|
||||||
|
"@angular/cli": "~6.0.3",
|
||||||
|
"@angular/language-service": "^6.0.2",
|
||||||
|
"@types/jasmine": "~2.8.6",
|
||||||
|
"@types/jasminewd2": "~2.0.3",
|
||||||
|
"@types/node": "~8.9.4",
|
||||||
|
"codelyzer": "~4.2.1",
|
||||||
|
"jasmine-core": "~2.99.1",
|
||||||
|
"jasmine-spec-reporter": "~4.2.1",
|
||||||
|
"karma": "~1.7.1",
|
||||||
|
"karma-chrome-launcher": "~2.2.0",
|
||||||
|
"karma-coverage-istanbul-reporter": "~1.4.2",
|
||||||
|
"karma-jasmine": "~1.1.1",
|
||||||
|
"karma-jasmine-html-reporter": "^0.2.2",
|
||||||
|
"protractor": "~5.3.0",
|
||||||
|
"ts-node": "~5.0.1",
|
||||||
|
"tslint": "~5.9.1"
|
||||||
|
}
|
||||||
|
}
|
31
projects/loafer/ng-logger/karma.conf.js
Normal file
31
projects/loafer/ng-logger/karma.conf.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// 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'),
|
||||||
|
reports: ['html', 'lcovonly'],
|
||||||
|
fixWebpackSourcePaths: true
|
||||||
|
},
|
||||||
|
reporters: ['progress', 'kjhtml'],
|
||||||
|
port: 9876,
|
||||||
|
colors: true,
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
autoWatch: true,
|
||||||
|
browsers: ['Chrome'],
|
||||||
|
singleRun: false
|
||||||
|
});
|
||||||
|
};
|
8
projects/loafer/ng-logger/ng-package.json
Normal file
8
projects/loafer/ng-logger/ng-package.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||||
|
"dest": "../../../dist/loafer/ng-logger",
|
||||||
|
"deleteDestPath": true,
|
||||||
|
"lib": {
|
||||||
|
"entryFile": "src/public_api.ts"
|
||||||
|
}
|
||||||
|
}
|
7
projects/loafer/ng-logger/ng-package.prod.json
Normal file
7
projects/loafer/ng-logger/ng-package.prod.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||||
|
"dest": "../../../dist/loafer/ng-logger",
|
||||||
|
"lib": {
|
||||||
|
"entryFile": "src/public_api.ts"
|
||||||
|
}
|
||||||
|
}
|
15
projects/loafer/ng-logger/package.json
Normal file
15
projects/loafer/ng-logger/package.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "@loafer/ng-logger",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.loafle.net/loafer/ng.git"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://nexus.loafle.net/repository/npm-loafle/"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^6.0.0-rc.0 || ^6.0.0",
|
||||||
|
"@angular/core": "^6.0.0-rc.0 || ^6.0.0"
|
||||||
|
}
|
||||||
|
}
|
6
projects/loafer/ng-logger/src/lib/ng-logger.config.ts
Normal file
6
projects/loafer/ng-logger/src/lib/ng-logger.config.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { LoggerLevel } from './ng-logger.type';
|
||||||
|
|
||||||
|
export class LoggerConfig {
|
||||||
|
level: LoggerLevel;
|
||||||
|
serverLogLevel?: LoggerLevel;
|
||||||
|
}
|
65
projects/loafer/ng-logger/src/lib/ng-logger.module.ts
Normal file
65
projects/loafer/ng-logger/src/lib/ng-logger.module.ts
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import {
|
||||||
|
NgModule,
|
||||||
|
ModuleWithProviders,
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
LoggerConfig,
|
||||||
|
} from './ng-logger.config';
|
||||||
|
|
||||||
|
import {
|
||||||
|
LoggerService,
|
||||||
|
} from './ng-logger.service';
|
||||||
|
|
||||||
|
export interface LoggerFeatureModuleConfig {
|
||||||
|
url?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LoggerRootModuleConfig {
|
||||||
|
config: LoggerConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SERVICES = [
|
||||||
|
LoggerService,
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class LoggerRootModule {
|
||||||
|
constructor(
|
||||||
|
private loggerService: LoggerService,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class LoggerFeatureModule {
|
||||||
|
constructor(
|
||||||
|
private loggerService: LoggerService,
|
||||||
|
private root: LoggerRootModule,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class LoggerModule {
|
||||||
|
static forRoot(config: LoggerRootModuleConfig): ModuleWithProviders {
|
||||||
|
return {
|
||||||
|
ngModule: LoggerRootModule,
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: LoggerConfig,
|
||||||
|
useValue: config.config,
|
||||||
|
},
|
||||||
|
SERVICES,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static forFeature(config: LoggerFeatureModuleConfig): ModuleWithProviders {
|
||||||
|
return {
|
||||||
|
ngModule: LoggerFeatureModule,
|
||||||
|
providers: [
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
15
projects/loafer/ng-logger/src/lib/ng-logger.service.spec.ts
Normal file
15
projects/loafer/ng-logger/src/lib/ng-logger.service.spec.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LoggerService } from './ng-logger.service';
|
||||||
|
|
||||||
|
describe('LoggerService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [LoggerService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([LoggerService], (service: LoggerService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
161
projects/loafer/ng-logger/src/lib/ng-logger.service.ts
Normal file
161
projects/loafer/ng-logger/src/lib/ng-logger.service.ts
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
import { Injectable, Inject, PLATFORM_ID } from '@angular/core';
|
||||||
|
import { isPlatformBrowser } from '@angular/common';
|
||||||
|
|
||||||
|
import {
|
||||||
|
LoggerConfig,
|
||||||
|
} from './ng-logger.config';
|
||||||
|
|
||||||
|
import {
|
||||||
|
LoggerLevel,
|
||||||
|
LoggerLevelName,
|
||||||
|
} from './ng-logger.type';
|
||||||
|
|
||||||
|
|
||||||
|
export type ConsoleFunc = (message?: any, ...optionalParams: any[]) => void;
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class LoggerService {
|
||||||
|
private _isIE: boolean;
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
private readonly config: LoggerConfig,
|
||||||
|
@Inject(PLATFORM_ID) private readonly platformId,
|
||||||
|
) {
|
||||||
|
this._isIE = isPlatformBrowser(platformId) &&
|
||||||
|
!!(navigator.userAgent.indexOf('MSIE') !== -1 || navigator.userAgent.match(/Trident\//) || navigator.userAgent.match(/Edge\//));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public get trace(): ConsoleFunc {
|
||||||
|
return this.getConsoleMethod(LoggerLevel.TRACE);
|
||||||
|
}
|
||||||
|
public get debug(): ConsoleFunc {
|
||||||
|
return this.getConsoleMethod(LoggerLevel.DEBUG);
|
||||||
|
}
|
||||||
|
public get info(): ConsoleFunc {
|
||||||
|
return this.getConsoleMethod(LoggerLevel.INFO);
|
||||||
|
}
|
||||||
|
public get log(): ConsoleFunc {
|
||||||
|
return this.getConsoleMethod(LoggerLevel.LOG);
|
||||||
|
}
|
||||||
|
public get warn(): ConsoleFunc {
|
||||||
|
return this.getConsoleMethod(LoggerLevel.WARN);
|
||||||
|
}
|
||||||
|
public get error(): ConsoleFunc {
|
||||||
|
return this.getConsoleMethod(LoggerLevel.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _console_log: ConsoleFunc;
|
||||||
|
|
||||||
|
private getConsoleMethod(level: LoggerLevel): ConsoleFunc {
|
||||||
|
if (level < this.config.level) {
|
||||||
|
return (message, ...additional: any[]) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._isIE) {
|
||||||
|
switch (level) {
|
||||||
|
case LoggerLevel.WARN:
|
||||||
|
return console.warn.bind(console, ...this.getLogHeader(level));
|
||||||
|
case LoggerLevel.ERROR:
|
||||||
|
return console.error.bind(console, ...this.getLogHeader(level));
|
||||||
|
case LoggerLevel.INFO:
|
||||||
|
return console.info.bind(console, ...this.getLogHeader(level));
|
||||||
|
default:
|
||||||
|
return console.log.bind(console, ...this.getLogHeader(level));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return console.log.bind(console, ...this.getLogHeader(level));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getLogHeader(level: LoggerLevel): any[] {
|
||||||
|
const params: any[] = [];
|
||||||
|
params.push(`%c${this._timestamp()} [${LoggerLevelName[level]}]`);
|
||||||
|
if (!this._isIE) {
|
||||||
|
const color = this._getColor(level);
|
||||||
|
params.push(`color:${color}`);
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _timestamp(): string {
|
||||||
|
return new Date().toISOString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _log(level: LoggerLevel, message, additional: any[] = []): void {
|
||||||
|
if (!message) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow logging on server even if client log level is off
|
||||||
|
// if (logOnServer) {
|
||||||
|
// this._logOnServer(level, message, additional);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if no message or the log level is less than the environ
|
||||||
|
if (level < this.config.level) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
message = typeof message === 'string' ? message : JSON.stringify(message, null, 2);
|
||||||
|
} catch (e) {
|
||||||
|
additional = [message, ...additional];
|
||||||
|
message = 'The provided "message" value could not be parsed with JSON.stringify().';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Coloring doesn't work in IE
|
||||||
|
if (this._isIE) {
|
||||||
|
return this._logIE(level, message, additional);
|
||||||
|
}
|
||||||
|
|
||||||
|
const color = this._getColor(level);
|
||||||
|
|
||||||
|
const params: any[] = [];
|
||||||
|
params.push(`%c${this._timestamp()} [${LoggerLevelName[level]}]`);
|
||||||
|
params.push(`color:${color}`);
|
||||||
|
params.push(message);
|
||||||
|
params.push(...additional);
|
||||||
|
|
||||||
|
console.log.apply(console, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _logIE(level: LoggerLevel, message: string, additional: any[] = []): void {
|
||||||
|
const params: any[] = [];
|
||||||
|
params.push(`${this._timestamp()} [${LoggerLevelName[level]}] `);
|
||||||
|
params.push(message);
|
||||||
|
params.push(...additional);
|
||||||
|
|
||||||
|
switch (level) {
|
||||||
|
case LoggerLevel.WARN:
|
||||||
|
console.warn.apply(console, params);
|
||||||
|
break;
|
||||||
|
case LoggerLevel.ERROR:
|
||||||
|
console.error.apply(console, params);
|
||||||
|
break;
|
||||||
|
case LoggerLevel.INFO:
|
||||||
|
console.info.apply(console, params);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log.apply(console, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getColor(level: LoggerLevel): 'blue' | 'teal' | 'gray' | 'red' | undefined {
|
||||||
|
switch (level) {
|
||||||
|
case LoggerLevel.TRACE:
|
||||||
|
return 'blue';
|
||||||
|
case LoggerLevel.DEBUG:
|
||||||
|
return 'teal';
|
||||||
|
case LoggerLevel.INFO:
|
||||||
|
case LoggerLevel.LOG:
|
||||||
|
return 'gray';
|
||||||
|
case LoggerLevel.WARN:
|
||||||
|
case LoggerLevel.ERROR:
|
||||||
|
return 'red';
|
||||||
|
case LoggerLevel.OFF:
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
projects/loafer/ng-logger/src/lib/ng-logger.type.ts
Normal file
26
projects/loafer/ng-logger/src/lib/ng-logger.type.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
export enum LoggerLevel {
|
||||||
|
TRACE = 0,
|
||||||
|
DEBUG,
|
||||||
|
INFO,
|
||||||
|
LOG,
|
||||||
|
WARN,
|
||||||
|
ERROR,
|
||||||
|
OFF,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LoggerLevelName = [
|
||||||
|
'TRACE',
|
||||||
|
'DEBUG',
|
||||||
|
'INFO',
|
||||||
|
'LOG',
|
||||||
|
'WARN',
|
||||||
|
'ERROR',
|
||||||
|
'OFF'
|
||||||
|
];
|
||||||
|
|
||||||
|
export interface ServerLoggingParameter {
|
||||||
|
level: string;
|
||||||
|
message: string;
|
||||||
|
addtional?: string;
|
||||||
|
timestamp: Date;
|
||||||
|
}
|
8
projects/loafer/ng-logger/src/public_api.ts
Normal file
8
projects/loafer/ng-logger/src/public_api.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/*
|
||||||
|
* Public API Surface of ng-logger
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './lib/ng-logger.config';
|
||||||
|
export * from './lib/ng-logger.type';
|
||||||
|
export * from './lib/ng-logger.service';
|
||||||
|
export * from './lib/ng-logger.module';
|
22
projects/loafer/ng-logger/src/test.ts
Normal file
22
projects/loafer/ng-logger/src/test.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||||
|
|
||||||
|
import 'core-js/es7/reflect';
|
||||||
|
import 'zone.js/dist/zone';
|
||||||
|
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);
|
33
projects/loafer/ng-logger/tsconfig.lib.json
Normal file
33
projects/loafer/ng-logger/tsconfig.lib.json
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../../out-tsc/lib",
|
||||||
|
"target": "es2015",
|
||||||
|
"module": "es2015",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"declaration": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"inlineSources": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"types": [],
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es2015"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"annotateForClosureCompiler": true,
|
||||||
|
"skipTemplateCodegen": true,
|
||||||
|
"strictMetadataEmit": true,
|
||||||
|
"fullTemplateTypeCheck": true,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"flatModuleId": "AUTOGENERATED",
|
||||||
|
"flatModuleOutFile": "AUTOGENERATED"
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"src/test.ts",
|
||||||
|
"**/*.spec.ts"
|
||||||
|
]
|
||||||
|
}
|
17
projects/loafer/ng-logger/tsconfig.spec.json
Normal file
17
projects/loafer/ng-logger/tsconfig.spec.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../../out-tsc/spec",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/test.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
17
projects/loafer/ng-logger/tslint.json
Normal file
17
projects/loafer/ng-logger/tslint.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tslint.json",
|
||||||
|
"rules": {
|
||||||
|
"directive-selector": [
|
||||||
|
true,
|
||||||
|
"attribute",
|
||||||
|
"lib",
|
||||||
|
"camelCase"
|
||||||
|
],
|
||||||
|
"component-selector": [
|
||||||
|
true,
|
||||||
|
"element",
|
||||||
|
"lib",
|
||||||
|
"kebab-case"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
31
projects/loafer/ng-rest/karma.conf.js
Normal file
31
projects/loafer/ng-rest/karma.conf.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// 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'),
|
||||||
|
reports: ['html', 'lcovonly'],
|
||||||
|
fixWebpackSourcePaths: true
|
||||||
|
},
|
||||||
|
reporters: ['progress', 'kjhtml'],
|
||||||
|
port: 9876,
|
||||||
|
colors: true,
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
autoWatch: true,
|
||||||
|
browsers: ['Chrome'],
|
||||||
|
singleRun: false
|
||||||
|
});
|
||||||
|
};
|
8
projects/loafer/ng-rest/ng-package.json
Normal file
8
projects/loafer/ng-rest/ng-package.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||||
|
"dest": "../../../dist/loafer/ng-rest",
|
||||||
|
"deleteDestPath": true,
|
||||||
|
"lib": {
|
||||||
|
"entryFile": "src/public_api.ts"
|
||||||
|
}
|
||||||
|
}
|
7
projects/loafer/ng-rest/ng-package.prod.json
Normal file
7
projects/loafer/ng-rest/ng-package.prod.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||||
|
"dest": "../../../dist/loafer/ng-rest",
|
||||||
|
"lib": {
|
||||||
|
"entryFile": "src/public_api.ts"
|
||||||
|
}
|
||||||
|
}
|
15
projects/loafer/ng-rest/package.json
Normal file
15
projects/loafer/ng-rest/package.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "@loafer/ng-rest",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.loafle.net/loafer/ng.git"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://nexus.loafle.net/repository/npm-loafle/"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^6.0.0-rc.0 || ^6.0.0",
|
||||||
|
"@angular/core": "^6.0.0-rc.0 || ^6.0.0"
|
||||||
|
}
|
||||||
|
}
|
65
projects/loafer/ng-rest/src/lib/ng-rest.client.ts
Normal file
65
projects/loafer/ng-rest/src/lib/ng-rest.client.ts
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
import { Location } from '@angular/common';
|
||||||
|
import { HttpClient, HttpHeaders, HttpParams, HttpErrorResponse } from '@angular/common/http';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import 'rxjs/add/operator/do';
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
import 'rxjs/add/operator/catch';
|
||||||
|
import 'rxjs/add/operator/timeout';
|
||||||
|
import 'rxjs/add/observable/throw';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RESTError,
|
||||||
|
RESTClientError,
|
||||||
|
} from './ng-rest.error';
|
||||||
|
|
||||||
|
export class RESTClient {
|
||||||
|
constructor(
|
||||||
|
private _baseURL: string,
|
||||||
|
private _httpClient: HttpClient,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public get httpClient(): HttpClient {
|
||||||
|
return this._httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public request<T>(method: string, entry: string, options?: {
|
||||||
|
body?: any;
|
||||||
|
headers?: HttpHeaders | {
|
||||||
|
[header: string]: string | string[];
|
||||||
|
};
|
||||||
|
observe?: 'body';
|
||||||
|
params?: HttpParams | {
|
||||||
|
[param: string]: string | string[];
|
||||||
|
};
|
||||||
|
responseType?: 'json';
|
||||||
|
reportProgress?: boolean;
|
||||||
|
withCredentials?: boolean;
|
||||||
|
}): Observable<T> {
|
||||||
|
return this._httpClient
|
||||||
|
.request<T>(method, Location.joinWithSlash(this._baseURL, entry), options)
|
||||||
|
.map(response => response)
|
||||||
|
.catch((error: HttpErrorResponse) => {
|
||||||
|
const restClientError: RESTClientError = {
|
||||||
|
request: {
|
||||||
|
method: method,
|
||||||
|
entry: entry,
|
||||||
|
options: options,
|
||||||
|
},
|
||||||
|
response: error.error,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.error(restClientError);
|
||||||
|
// const aryMsg = error.error.message.split('|');
|
||||||
|
// const resError: RESTError = {
|
||||||
|
// code: error.error.code,
|
||||||
|
// message: aryMsg[0],
|
||||||
|
// data: aryMsg[1] === 'null' ? '' : aryMsg[1],
|
||||||
|
// };
|
||||||
|
return Observable.throw(restClientError);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
14
projects/loafer/ng-rest/src/lib/ng-rest.error.ts
Normal file
14
projects/loafer/ng-rest/src/lib/ng-rest.error.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
export interface RESTClientError {
|
||||||
|
request: {
|
||||||
|
method: string;
|
||||||
|
entry: string;
|
||||||
|
options?: any;
|
||||||
|
};
|
||||||
|
response: RESTError;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RESTError {
|
||||||
|
code: number;
|
||||||
|
message: string;
|
||||||
|
data?: any;
|
||||||
|
}
|
68
projects/loafer/ng-rest/src/lib/ng-rest.module.ts
Normal file
68
projects/loafer/ng-rest/src/lib/ng-rest.module.ts
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import {
|
||||||
|
NgModule,
|
||||||
|
ModuleWithProviders,
|
||||||
|
Type,
|
||||||
|
Inject,
|
||||||
|
InjectionToken,
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
_REST_BASE_URL,
|
||||||
|
} from './ng-rest.token';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RESTService,
|
||||||
|
} from './ng-rest.service';
|
||||||
|
|
||||||
|
export interface RESTFeatureModuleConfig {
|
||||||
|
url?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RESTRootModuleConfig {
|
||||||
|
baseURL: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SERVICES = [
|
||||||
|
RESTService,
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class RESTRootModule {
|
||||||
|
constructor(
|
||||||
|
private restService: RESTService,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class RESTFeatureModule {
|
||||||
|
constructor(
|
||||||
|
private restService: RESTService,
|
||||||
|
private root: RESTRootModule,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class RESTModule {
|
||||||
|
static forRoot(config: RESTRootModuleConfig): ModuleWithProviders {
|
||||||
|
return {
|
||||||
|
ngModule: RESTRootModule,
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: _REST_BASE_URL,
|
||||||
|
useValue: config.baseURL,
|
||||||
|
},
|
||||||
|
SERVICES,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static forFeature(config: RESTFeatureModuleConfig): ModuleWithProviders {
|
||||||
|
return {
|
||||||
|
ngModule: RESTFeatureModule,
|
||||||
|
providers: [
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
16
projects/loafer/ng-rest/src/lib/ng-rest.service.spec.ts
Normal file
16
projects/loafer/ng-rest/src/lib/ng-rest.service.spec.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import {} from 'jasmine';
|
||||||
|
|
||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
import { RESTService } from './ng-rest.service';
|
||||||
|
|
||||||
|
describe('RESTService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [RESTService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([RESTService], (service: RESTService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
26
projects/loafer/ng-rest/src/lib/ng-rest.service.ts
Normal file
26
projects/loafer/ng-rest/src/lib/ng-rest.service.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
import { Location } from '@angular/common';
|
||||||
|
|
||||||
|
import 'rxjs/add/operator/do';
|
||||||
|
import 'rxjs/add/operator/map';
|
||||||
|
import 'rxjs/add/operator/catch';
|
||||||
|
import 'rxjs/add/operator/timeout';
|
||||||
|
import 'rxjs/add/observable/throw';
|
||||||
|
|
||||||
|
import { _REST_BASE_URL } from './ng-rest.token';
|
||||||
|
import { RESTClient } from './ng-rest.client';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RESTService extends RESTClient {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(_REST_BASE_URL) _baseURL: string,
|
||||||
|
@Inject(HttpClient) _httpClient: HttpClient,
|
||||||
|
) {
|
||||||
|
super(_baseURL, _httpClient);
|
||||||
|
}
|
||||||
|
}
|
3
projects/loafer/ng-rest/src/lib/ng-rest.token.ts
Normal file
3
projects/loafer/ng-rest/src/lib/ng-rest.token.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import { InjectionToken } from '@angular/core';
|
||||||
|
|
||||||
|
export const _REST_BASE_URL = new InjectionToken('@loafer/ng-rest Internal Base URL');
|
7
projects/loafer/ng-rest/src/public_api.ts
Normal file
7
projects/loafer/ng-rest/src/public_api.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
/*
|
||||||
|
* Public API Surface of ng-rest
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './lib/ng-rest.error';
|
||||||
|
export * from './lib/ng-rest.service';
|
||||||
|
export * from './lib/ng-rest.module';
|
22
projects/loafer/ng-rest/src/test.ts
Normal file
22
projects/loafer/ng-rest/src/test.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||||
|
|
||||||
|
import 'core-js/es7/reflect';
|
||||||
|
import 'zone.js/dist/zone';
|
||||||
|
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);
|
33
projects/loafer/ng-rest/tsconfig.lib.json
Normal file
33
projects/loafer/ng-rest/tsconfig.lib.json
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../../out-tsc/lib",
|
||||||
|
"target": "es2015",
|
||||||
|
"module": "es2015",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"declaration": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"inlineSources": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"types": [],
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es2015"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"annotateForClosureCompiler": true,
|
||||||
|
"skipTemplateCodegen": true,
|
||||||
|
"strictMetadataEmit": true,
|
||||||
|
"fullTemplateTypeCheck": true,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"flatModuleId": "AUTOGENERATED",
|
||||||
|
"flatModuleOutFile": "AUTOGENERATED"
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"src/test.ts",
|
||||||
|
"**/*.spec.ts"
|
||||||
|
]
|
||||||
|
}
|
17
projects/loafer/ng-rest/tsconfig.spec.json
Normal file
17
projects/loafer/ng-rest/tsconfig.spec.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../../out-tsc/spec",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/test.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
17
projects/loafer/ng-rest/tslint.json
Normal file
17
projects/loafer/ng-rest/tslint.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tslint.json",
|
||||||
|
"rules": {
|
||||||
|
"directive-selector": [
|
||||||
|
true,
|
||||||
|
"attribute",
|
||||||
|
"lib",
|
||||||
|
"camelCase"
|
||||||
|
],
|
||||||
|
"component-selector": [
|
||||||
|
true,
|
||||||
|
"element",
|
||||||
|
"lib",
|
||||||
|
"kebab-case"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
31
projects/loafer/ng-rpc/karma.conf.js
Normal file
31
projects/loafer/ng-rpc/karma.conf.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// 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'),
|
||||||
|
reports: ['html', 'lcovonly'],
|
||||||
|
fixWebpackSourcePaths: true
|
||||||
|
},
|
||||||
|
reporters: ['progress', 'kjhtml'],
|
||||||
|
port: 9876,
|
||||||
|
colors: true,
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
autoWatch: true,
|
||||||
|
browsers: ['Chrome'],
|
||||||
|
singleRun: false
|
||||||
|
});
|
||||||
|
};
|
8
projects/loafer/ng-rpc/ng-package.json
Normal file
8
projects/loafer/ng-rpc/ng-package.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||||
|
"dest": "../../../dist/loafer/ng-rpc",
|
||||||
|
"deleteDestPath": true,
|
||||||
|
"lib": {
|
||||||
|
"entryFile": "src/public_api.ts"
|
||||||
|
}
|
||||||
|
}
|
7
projects/loafer/ng-rpc/ng-package.prod.json
Normal file
7
projects/loafer/ng-rpc/ng-package.prod.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
|
||||||
|
"dest": "../../../dist/loafer/ng-rpc",
|
||||||
|
"lib": {
|
||||||
|
"entryFile": "src/public_api.ts"
|
||||||
|
}
|
||||||
|
}
|
15
projects/loafer/ng-rpc/package.json
Normal file
15
projects/loafer/ng-rpc/package.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "@loafer/ng-rpc",
|
||||||
|
"version": "0.0.6",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.loafle.net/loafer/ng.git"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://nexus.loafle.net/repository/npm-loafle/"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^6.0.0-rc.0 || ^6.0.0",
|
||||||
|
"@angular/core": "^6.0.0-rc.0 || ^6.0.0"
|
||||||
|
}
|
||||||
|
}
|
146
projects/loafer/ng-rpc/src/lib/client/RPCClient.ts
Normal file
146
projects/loafer/ng-rpc/src/lib/client/RPCClient.ts
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { Subject } from 'rxjs/Subject';
|
||||||
|
|
||||||
|
import { RPCClientError } from '../protocol/RPCError';
|
||||||
|
import { RPCClientRWC } from './RPCClientRWC';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCClientCodec,
|
||||||
|
RPCClientResponseCodec,
|
||||||
|
RPCClientNotificationCodec,
|
||||||
|
} from '../protocol/RPCClientCodec';
|
||||||
|
|
||||||
|
export interface RPCRequestState {
|
||||||
|
subject: Subject<any>;
|
||||||
|
request: {
|
||||||
|
method: string;
|
||||||
|
params: any[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class RPCClient<T> {
|
||||||
|
private _requestID: number;
|
||||||
|
|
||||||
|
private _pendingRequestsCount: number;
|
||||||
|
private _pendingRequests: Map<number, RPCRequestState>;
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
private _codec: RPCClientCodec,
|
||||||
|
private _rwc: RPCClientRWC<T>,
|
||||||
|
) {
|
||||||
|
this._requestID = 0;
|
||||||
|
this._pendingRequestsCount = 0;
|
||||||
|
this._pendingRequests = new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
private getRequestID(): number {
|
||||||
|
return ++this._requestID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* connect
|
||||||
|
*/
|
||||||
|
public connect(queryString?: string): void {
|
||||||
|
this._rwc.connect(queryString);
|
||||||
|
this._rwc.readResponse().subscribe(
|
||||||
|
(value: T) => {
|
||||||
|
this.onMessage(value);
|
||||||
|
},
|
||||||
|
(error: any) => {
|
||||||
|
console.error(error);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* close
|
||||||
|
*/
|
||||||
|
public disconnect() {
|
||||||
|
this._rwc.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* notify
|
||||||
|
*/
|
||||||
|
public send(method: string, ...args: any[]): void {
|
||||||
|
this.sendInternal(false, method, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* call
|
||||||
|
*/
|
||||||
|
public call<RT>(method: string, ...args: any[]): Observable<RT> {
|
||||||
|
return this.sendInternal<RT>(true, method, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* callTimeout
|
||||||
|
*/
|
||||||
|
public callTimeout<RT>(ms: number, method: string, ...args: any[]): Observable<RT> {
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private sendInternal<RT>(hasResponse: boolean, method: string, args?: any[]): Observable<RT> | undefined {
|
||||||
|
let id: number;
|
||||||
|
let resSubject: Subject<RT>;
|
||||||
|
if (hasResponse) {
|
||||||
|
id = this.getRequestID();
|
||||||
|
resSubject = new Subject<RT>();
|
||||||
|
const reqState: RPCRequestState = {
|
||||||
|
subject: resSubject,
|
||||||
|
request: {
|
||||||
|
method: method,
|
||||||
|
params: args,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this._pendingRequests.set(id, reqState);
|
||||||
|
this._pendingRequestsCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const req = this._codec.request(method, args, id);
|
||||||
|
this._rwc.writeRequest(req);
|
||||||
|
|
||||||
|
if (undefined !== resSubject) {
|
||||||
|
return resSubject.asObservable();
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private onMessage(message: Object): void {
|
||||||
|
const resCodec = this._codec.response(message);
|
||||||
|
|
||||||
|
if (resCodec.isNotification()) {
|
||||||
|
this.onNotification(resCodec.notification());
|
||||||
|
} else {
|
||||||
|
this.onResponse(resCodec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onResponse(resCodec: RPCClientResponseCodec): void {
|
||||||
|
const id = resCodec.id();
|
||||||
|
const result = resCodec.result();
|
||||||
|
const error = resCodec.error();
|
||||||
|
|
||||||
|
const reqState: RPCRequestState = this._pendingRequests.get(id);
|
||||||
|
|
||||||
|
this._pendingRequests.delete(id);
|
||||||
|
this._pendingRequestsCount--;
|
||||||
|
|
||||||
|
if (undefined !== result) {
|
||||||
|
reqState.subject.next(result);
|
||||||
|
} else if (undefined !== error) {
|
||||||
|
const rpcClientError: RPCClientError = {
|
||||||
|
request: reqState.request,
|
||||||
|
response: error,
|
||||||
|
};
|
||||||
|
console.error(rpcClientError);
|
||||||
|
reqState.subject.error(rpcClientError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract onNotification(notiCodec: RPCClientNotificationCodec): void;
|
||||||
|
}
|
11
projects/loafer/ng-rpc/src/lib/client/RPCClientRWC.ts
Normal file
11
projects/loafer/ng-rpc/src/lib/client/RPCClientRWC.ts
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { InjectionToken } from '@angular/core';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
export interface RPCClientRWC<T> {
|
||||||
|
connect(queryString?: string): void;
|
||||||
|
readResponse(): Observable<T>;
|
||||||
|
writeRequest(data: any): void;
|
||||||
|
disconnect(): void;
|
||||||
|
connectionStatus(): Observable<boolean>;
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { Subject } from 'rxjs/Subject';
|
||||||
|
import { map } from 'rxjs/operator/map';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RxWebsocketSubject,
|
||||||
|
RxWebsocketSubjectConfig,
|
||||||
|
} from './RxWebsocketSubject';
|
||||||
|
|
||||||
|
import { RPCClientRWC } from '../../RPCClientRWC';
|
||||||
|
|
||||||
|
export class RPCClientWebsocketRWC<T> implements RPCClientRWC<T> {
|
||||||
|
private _wsSocketSubject: RxWebsocketSubject<T>;
|
||||||
|
private _responseSubject: Subject<T>;
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
private _config: RxWebsocketSubjectConfig,
|
||||||
|
) {
|
||||||
|
this._wsSocketSubject = new RxWebsocketSubject<T>(this._config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public connect(queryString?: string): void {
|
||||||
|
if (undefined !== queryString) {
|
||||||
|
this._wsSocketSubject.queryString = queryString;
|
||||||
|
}
|
||||||
|
this._wsSocketSubject.connect();
|
||||||
|
this._wsSocketSubject.subscribe(
|
||||||
|
(value: T) => {
|
||||||
|
if (undefined !== this._responseSubject) {
|
||||||
|
this._responseSubject.next(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(error: any) => {
|
||||||
|
if (undefined !== this._responseSubject) {
|
||||||
|
this._responseSubject.error(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
console.log('sss');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public disconnect(): void {
|
||||||
|
this._wsSocketSubject.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public connectionStatus(): Observable<boolean> {
|
||||||
|
return this._wsSocketSubject.connectionStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readResponse(): Observable<T> {
|
||||||
|
if (undefined === this._responseSubject) {
|
||||||
|
this._responseSubject = new Subject<T>();
|
||||||
|
}
|
||||||
|
return this._responseSubject.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public writeRequest(data: any): void {
|
||||||
|
this._wsSocketSubject.write(data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { Observer } from 'rxjs/Observer';
|
||||||
|
import { Subject } from 'rxjs/Subject';
|
||||||
|
import {
|
||||||
|
WebSocketSubject,
|
||||||
|
WebSocketSubjectConfig
|
||||||
|
} from 'rxjs/observable/dom/WebSocketSubject';
|
||||||
|
|
||||||
|
import 'rxjs/add/operator/distinctUntilChanged';
|
||||||
|
import 'rxjs/add/operator/share';
|
||||||
|
import 'rxjs/add/operator/takeWhile';
|
||||||
|
import 'rxjs/add/observable/interval';
|
||||||
|
|
||||||
|
export interface RxWebsocketSubjectConfig {
|
||||||
|
url: string;
|
||||||
|
protocol?: string | Array<string>;
|
||||||
|
reconnectInterval?: 5000;
|
||||||
|
reconnectRetry?: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RxWebsocketSubject<T> extends Subject<T> {
|
||||||
|
private _reconnectionObservable: Observable<number>;
|
||||||
|
private _wsSubjectConfig: WebSocketSubjectConfig<T>;
|
||||||
|
private _socket: WebSocketSubject<any>;
|
||||||
|
private _connectionObserver: Observer<boolean>;
|
||||||
|
private _connectionStatus: Observable<boolean>;
|
||||||
|
private _queryString: string;
|
||||||
|
|
||||||
|
public constructor(private _config: RxWebsocketSubjectConfig) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._connectionStatus = new Observable<boolean>((observer) => {
|
||||||
|
this._connectionObserver = observer;
|
||||||
|
}).share().distinctUntilChanged();
|
||||||
|
|
||||||
|
this._wsSubjectConfig = {
|
||||||
|
url: _config.url,
|
||||||
|
protocol: _config.protocol,
|
||||||
|
serializer: (value: any) => value,
|
||||||
|
closeObserver: {
|
||||||
|
next: (e: CloseEvent) => {
|
||||||
|
this._socket = null;
|
||||||
|
this._connectionObserver.next(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openObserver: {
|
||||||
|
next: (e: Event) => {
|
||||||
|
this._connectionObserver.next(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this._connectionStatus.subscribe((isConnected: boolean) => {
|
||||||
|
if (!this._reconnectionObservable && typeof(isConnected) === 'boolean' && !isConnected) {
|
||||||
|
this.reconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public set queryString(query: string) {
|
||||||
|
this._queryString = query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get queryString(): string | undefined {
|
||||||
|
return this._queryString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get connectionStatus(): Observable<boolean> {
|
||||||
|
return this._connectionStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public connect(): void {
|
||||||
|
const wsSubjectConfig = Object.assign({}, this._wsSubjectConfig);
|
||||||
|
if (undefined !== this._queryString) {
|
||||||
|
wsSubjectConfig.url = wsSubjectConfig.url + '?' + this._queryString;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._socket = new WebSocketSubject(wsSubjectConfig);
|
||||||
|
this._socket.subscribe(
|
||||||
|
(m) => {
|
||||||
|
this.next(m);
|
||||||
|
},
|
||||||
|
(error: Event) => {
|
||||||
|
if (!this._socket) {
|
||||||
|
this.reconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public disconnect(): void {
|
||||||
|
this._socket.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private reconnect(): void {
|
||||||
|
this._reconnectionObservable = Observable.interval(this._config.reconnectInterval)
|
||||||
|
.takeWhile((v, index) => {
|
||||||
|
return index < this._config.reconnectRetry && !this._socket;
|
||||||
|
});
|
||||||
|
this._reconnectionObservable.subscribe(
|
||||||
|
() => {
|
||||||
|
this.connect();
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
() => {
|
||||||
|
this._reconnectionObservable = null;
|
||||||
|
if (!this._socket) {
|
||||||
|
this.complete();
|
||||||
|
this._connectionObserver.complete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public write(data: any): void {
|
||||||
|
this._socket.next(data);
|
||||||
|
}
|
||||||
|
}
|
6
projects/loafer/ng-rpc/src/lib/core/error.ts
Normal file
6
projects/loafer/ng-rpc/src/lib/core/error.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export class SubscriberParameterError extends Error {
|
||||||
|
public constructor(message?: string) {
|
||||||
|
super(message);
|
||||||
|
Object.setPrototypeOf(this, new.target.prototype);
|
||||||
|
}
|
||||||
|
}
|
8
projects/loafer/ng-rpc/src/lib/core/token.ts
Normal file
8
projects/loafer/ng-rpc/src/lib/core/token.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { InjectionToken } from '@angular/core';
|
||||||
|
|
||||||
|
export const RPC_CODEC = new InjectionToken('@loafer/ng-rpc RPC codec');
|
||||||
|
export const RPC_RWC = new InjectionToken('@loafer/ng-rpc RPC rwc');
|
||||||
|
|
||||||
|
export const _ROOT_SUBSCRIBERS = new InjectionToken('@loafer/ng-rpc RPC root subscribers');
|
||||||
|
export const _FEATURE_SUBSCRIBERS = new InjectionToken('@loafer/ng-rpc RPC feature subscribers');
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import {
|
||||||
|
Type,
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '@loafer/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Annotation,
|
||||||
|
} from '@loafer/core/reflect';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Decorator,
|
||||||
|
} from '@loafer/decorator';
|
||||||
|
|
||||||
|
export class RPCSubscriberAnnotation extends Annotation {
|
||||||
|
method: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RPCSubscriber(config: RPCSubscriberAnnotation): MethodDecorator {
|
||||||
|
return function<T>(target: Object, propertyKey: PropertyKeyType, descriptor: TypedPropertyDescriptor<T>)
|
||||||
|
: TypedPropertyDescriptor<T> | void {
|
||||||
|
|
||||||
|
Decorator.register(RPCSubscriberAnnotation, config, target, propertyKey, descriptor);
|
||||||
|
};
|
||||||
|
}
|
106
projects/loafer/ng-rpc/src/lib/ng-rpc.module.ts
Normal file
106
projects/loafer/ng-rpc/src/lib/ng-rpc.module.ts
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
import {
|
||||||
|
NgModule,
|
||||||
|
ModuleWithProviders,
|
||||||
|
Type,
|
||||||
|
Inject,
|
||||||
|
InjectionToken,
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPC_CODEC,
|
||||||
|
RPC_RWC,
|
||||||
|
|
||||||
|
_ROOT_SUBSCRIBERS,
|
||||||
|
_FEATURE_SUBSCRIBERS,
|
||||||
|
} from './core/token';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCClientRWC,
|
||||||
|
} from './client/RPCClientRWC';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCClientCodec,
|
||||||
|
} from './protocol/RPCClientCodec';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCService,
|
||||||
|
} from './service/rpc.service';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCSubscribeService,
|
||||||
|
} from './subscribe/subscribe.service';
|
||||||
|
|
||||||
|
const SERVICES = [
|
||||||
|
RPCService,
|
||||||
|
];
|
||||||
|
|
||||||
|
const SUBSCRIBERS = [
|
||||||
|
RPCSubscribeService,
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class RPCRootModule {
|
||||||
|
constructor(
|
||||||
|
private rpcService: RPCService,
|
||||||
|
private rpcSubscribeService: RPCSubscribeService,
|
||||||
|
@Inject(_ROOT_SUBSCRIBERS) rootSubscribers: any[],
|
||||||
|
) {
|
||||||
|
rootSubscribers.forEach((subscriber) => {
|
||||||
|
rpcSubscribeService.addSubscriber(subscriber);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class RPCFeatureModule {
|
||||||
|
constructor(
|
||||||
|
private rpcService: RPCService,
|
||||||
|
private rpcSubscribeService: RPCSubscribeService,
|
||||||
|
@Inject(_FEATURE_SUBSCRIBERS) featureSubscribersGroups: any[][],
|
||||||
|
private root: RPCRootModule,
|
||||||
|
) {
|
||||||
|
featureSubscribersGroups.forEach((featureSubscribers) => {
|
||||||
|
featureSubscribers.forEach((subscriber) => {
|
||||||
|
rpcSubscribeService.addSubscriber(subscriber);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({})
|
||||||
|
export class RPCModule {
|
||||||
|
static forRoot(subscribers: Type<any>[]): ModuleWithProviders {
|
||||||
|
return {
|
||||||
|
ngModule: RPCRootModule,
|
||||||
|
providers: [
|
||||||
|
subscribers,
|
||||||
|
{
|
||||||
|
provide: _ROOT_SUBSCRIBERS,
|
||||||
|
deps: subscribers,
|
||||||
|
useFactory: createSourceInstances,
|
||||||
|
},
|
||||||
|
SERVICES,
|
||||||
|
SUBSCRIBERS,
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static forFeature(subscribers: Type<any>[]): ModuleWithProviders {
|
||||||
|
return {
|
||||||
|
ngModule: RPCFeatureModule,
|
||||||
|
providers: [
|
||||||
|
subscribers,
|
||||||
|
{
|
||||||
|
provide: _FEATURE_SUBSCRIBERS,
|
||||||
|
multi: true,
|
||||||
|
deps: subscribers,
|
||||||
|
useFactory: createSourceInstances,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createSourceInstances(...instances: any[]) {
|
||||||
|
return instances;
|
||||||
|
}
|
20
projects/loafer/ng-rpc/src/lib/protocol/RPCClientCodec.ts
Normal file
20
projects/loafer/ng-rpc/src/lib/protocol/RPCClientCodec.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { RPCError } from './RPCError';
|
||||||
|
|
||||||
|
export interface RPCClientCodec {
|
||||||
|
request(method: string, args: any[], id: number): any;
|
||||||
|
response(res: any): RPCClientResponseCodec;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RPCClientResponseCodec {
|
||||||
|
id(): number | undefined;
|
||||||
|
error(): RPCError | undefined;
|
||||||
|
result(): any | undefined;
|
||||||
|
|
||||||
|
isNotification(): boolean;
|
||||||
|
notification(): RPCClientNotificationCodec | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RPCClientNotificationCodec {
|
||||||
|
method(): string;
|
||||||
|
params(): any | undefined;
|
||||||
|
}
|
41
projects/loafer/ng-rpc/src/lib/protocol/RPCError.ts
Normal file
41
projects/loafer/ng-rpc/src/lib/protocol/RPCError.ts
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
export interface RPCClientError {
|
||||||
|
request: {
|
||||||
|
method: string,
|
||||||
|
params: any[],
|
||||||
|
};
|
||||||
|
response: RPCError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error object representation when a method invocation fails.
|
||||||
|
*/
|
||||||
|
export interface RPCError {
|
||||||
|
/** Indicates the error type that occurred. */
|
||||||
|
code: RPCErrorCode;
|
||||||
|
|
||||||
|
/** A short description of the error. */
|
||||||
|
message: string;
|
||||||
|
|
||||||
|
/** Additional information about the error */
|
||||||
|
data?: any;
|
||||||
|
}/*
|
||||||
|
|
||||||
|
/** Error codes are same as xml-rpc codes. See http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php */
|
||||||
|
export const enum RPCErrorCode {
|
||||||
|
/** Parse error Invalid JSON was received by the Server. */
|
||||||
|
ParseError = -32700,
|
||||||
|
|
||||||
|
/** Invalid Request The JSON sent is not a valid Request object. */
|
||||||
|
InvalidRequest = -32600,
|
||||||
|
|
||||||
|
/** The method does not exist / is not available. */
|
||||||
|
MethodNotFound = -32601,
|
||||||
|
|
||||||
|
/** Invalid method parameter(s). */
|
||||||
|
InvalidParams = - -32602,
|
||||||
|
|
||||||
|
/** Internal JSON-RPC error. */
|
||||||
|
InternalError = -32603
|
||||||
|
|
||||||
|
/** -32000 to -32099: Reserved for implementation-defined Server errors. */
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
import {
|
||||||
|
RPCClientCodec,
|
||||||
|
RPCClientResponseCodec,
|
||||||
|
RPCClientNotificationCodec,
|
||||||
|
} from '../RPCClientCodec';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCError,
|
||||||
|
} from '../RPCError';
|
||||||
|
|
||||||
|
export interface ClientNotification {
|
||||||
|
method: string;
|
||||||
|
params?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ClientRequest {
|
||||||
|
jsonrpc: string;
|
||||||
|
method: string;
|
||||||
|
params?: string[];
|
||||||
|
id?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ClientResponse {
|
||||||
|
jsonrpc: string;
|
||||||
|
result?: any;
|
||||||
|
error?: RPCError;
|
||||||
|
id?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class JSONRPCClientCodec implements RPCClientCodec {
|
||||||
|
public request(method: string, args: any[], id?: number): any {
|
||||||
|
const params = convertParamsToStringArray(args);
|
||||||
|
|
||||||
|
const req: ClientRequest = {
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
method: method,
|
||||||
|
params: 0 === params.length ? null : params,
|
||||||
|
id: id,
|
||||||
|
};
|
||||||
|
return JSON.stringify(req);
|
||||||
|
}
|
||||||
|
public response(res: any): RPCClientResponseCodec {
|
||||||
|
const _res: ClientResponse = {
|
||||||
|
id: res.id,
|
||||||
|
jsonrpc: res.jsonrpc,
|
||||||
|
result: res.result,
|
||||||
|
error: res.error,
|
||||||
|
};
|
||||||
|
return new JSONRPCClientResponseCodec(_res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertParamsToStringArray(args: any[]): string[] | undefined {
|
||||||
|
const values: string[] = [];
|
||||||
|
|
||||||
|
if (undefined === args || null === args || 0 === args.length) {
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let indexI = 0; indexI < args.length; indexI++) {
|
||||||
|
const arg = args[indexI];
|
||||||
|
|
||||||
|
switch (typeof arg) {
|
||||||
|
case 'boolean':
|
||||||
|
case 'number': // enum
|
||||||
|
values.push(String(arg));
|
||||||
|
break;
|
||||||
|
case 'string':
|
||||||
|
values.push(arg);
|
||||||
|
break;
|
||||||
|
case 'object': // array, map
|
||||||
|
values.push(JSON.stringify(arg));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Not supported type[${typeof arg}]`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class JSONRPCClientResponseCodec implements RPCClientResponseCodec {
|
||||||
|
public constructor(private _res: ClientResponse) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public id(): number | undefined {
|
||||||
|
return this._res.id;
|
||||||
|
}
|
||||||
|
public error(): RPCError | undefined {
|
||||||
|
return this._res.error;
|
||||||
|
}
|
||||||
|
public result(): any | undefined {
|
||||||
|
return this._res.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isNotification(): boolean {
|
||||||
|
if (undefined !== this.id() || undefined === this.result()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public notification(): RPCClientNotificationCodec | undefined {
|
||||||
|
if (undefined !== this.id() || undefined === this.result()) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const _noti: ClientNotification = {
|
||||||
|
method: this._res.result.method,
|
||||||
|
params: this._res.result.params,
|
||||||
|
};
|
||||||
|
return new JSONRPCClientNotificationCodec(_noti);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class JSONRPCClientNotificationCodec implements RPCClientNotificationCodec {
|
||||||
|
public constructor(private _noti: ClientNotification) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public method(): string {
|
||||||
|
return this._noti.method;
|
||||||
|
}
|
||||||
|
public params(): any[] | undefined {
|
||||||
|
return this._noti.params;
|
||||||
|
}
|
||||||
|
}
|
33
projects/loafer/ng-rpc/src/lib/service/rpc.service.ts
Normal file
33
projects/loafer/ng-rpc/src/lib/service/rpc.service.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { Subject } from 'rxjs/Subject';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPC_CODEC,
|
||||||
|
RPC_RWC,
|
||||||
|
} from '../core/token';
|
||||||
|
|
||||||
|
import { RPCClient } from '../client/RPCClient';
|
||||||
|
import { RPCClientRWC } from '../client/RPCClientRWC';
|
||||||
|
import { RPCClientCodec, RPCClientNotificationCodec } from '../protocol/RPCClientCodec';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCSubscribeService,
|
||||||
|
} from '../subscribe/subscribe.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RPCService extends RPCClient<any> {
|
||||||
|
constructor(
|
||||||
|
@Inject(RPC_CODEC) rpcClientCodec: RPCClientCodec,
|
||||||
|
@Inject(RPC_RWC) rpcClientRWC: RPCClientRWC<any>,
|
||||||
|
private rpcSubscribeService: RPCSubscribeService,
|
||||||
|
) {
|
||||||
|
super(rpcClientCodec, rpcClientRWC);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onNotification(notiCodec: RPCClientNotificationCodec): void {
|
||||||
|
this.rpcSubscribeService.notify(notiCodec);
|
||||||
|
}
|
||||||
|
}
|
162
projects/loafer/ng-rpc/src/lib/subscribe/subscribe.service.ts
Normal file
162
projects/loafer/ng-rpc/src/lib/subscribe/subscribe.service.ts
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
import { Store, select } from '@ngrx/store';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Type,
|
||||||
|
PropertyKeyType,
|
||||||
|
} from '@loafer/core';
|
||||||
|
|
||||||
|
import { TypeUtil } from '@loafer/core/util/TypeUtil';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Class,
|
||||||
|
Method,
|
||||||
|
Metadata,
|
||||||
|
} from '@loafer/core/reflect';
|
||||||
|
|
||||||
|
import { RPCSubscriberAnnotation } from '../decorator/rpc-subscriber.decorator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
RPCClientNotificationCodec,
|
||||||
|
} from '../protocol/RPCClientCodec';
|
||||||
|
|
||||||
|
import { SubscriberParameterError } from '../core/error';
|
||||||
|
|
||||||
|
export interface SubscriberMethod {
|
||||||
|
className: PropertyKeyType;
|
||||||
|
methodName: PropertyKeyType;
|
||||||
|
parameterTypes: string[];
|
||||||
|
|
||||||
|
method: Method;
|
||||||
|
instance: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RPCSubscribeService {
|
||||||
|
private subscriberTypes: Set<Type<any>>;
|
||||||
|
private subscribers: Set<any>;
|
||||||
|
private subscriberMethodMap: Map<string, SubscriberMethod[]>;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
) {
|
||||||
|
this.subscriberTypes = new Set();
|
||||||
|
this.subscribers = new Set();
|
||||||
|
this.subscriberMethodMap = new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
public addSubscriber(subscriber: Type<any>): void {
|
||||||
|
const type = TypeUtil.getType(subscriber);
|
||||||
|
|
||||||
|
if (this.subscriberTypes.has(type)) {
|
||||||
|
// console.log(`Subscriber[${type.name}] has been added`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.subscriberTypes.add(type);
|
||||||
|
|
||||||
|
const clazz = Class.forType(type);
|
||||||
|
if (undefined === clazz) {
|
||||||
|
console.log(`Type[${subscriber.name}] is not decorated type`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const methods = clazz.getMethods();
|
||||||
|
methods.forEach((method, propertyKey) => {
|
||||||
|
const annon = method.getAnnotation(RPCSubscriberAnnotation);
|
||||||
|
if (undefined === annon) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const subscriberMethodName = annon.method;
|
||||||
|
let subscriberMethods: SubscriberMethod[] = this.subscriberMethodMap.get(subscriberMethodName);
|
||||||
|
if (undefined === subscriberMethods) {
|
||||||
|
subscriberMethods = [];
|
||||||
|
this.subscriberMethodMap.set(subscriberMethodName, subscriberMethods);
|
||||||
|
}
|
||||||
|
|
||||||
|
const paramTypes = this.getParamTypes(method);
|
||||||
|
|
||||||
|
const subscriberMethod: SubscriberMethod = {
|
||||||
|
className: clazz.getName(),
|
||||||
|
methodName: method.getName(),
|
||||||
|
parameterTypes: paramTypes,
|
||||||
|
method: method,
|
||||||
|
instance: subscriber,
|
||||||
|
};
|
||||||
|
|
||||||
|
subscriberMethods.push(subscriberMethod);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public notify(codec: RPCClientNotificationCodec): void {
|
||||||
|
const method = codec.method();
|
||||||
|
const params = codec.params();
|
||||||
|
|
||||||
|
const subscriberMethods: SubscriberMethod[] = this.subscriberMethodMap.get(method);
|
||||||
|
if (undefined === subscriberMethods) {
|
||||||
|
console.warn(`Subscriber for method[${method}] is not exist`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
subscriberMethods.forEach((subscriberMethod) => {
|
||||||
|
try {
|
||||||
|
const args = this.converParams(params, subscriberMethod.parameterTypes);
|
||||||
|
subscriberMethod.method.invoke(subscriberMethod.instance, ...args);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private getParamTypes(method: Method): string[] {
|
||||||
|
if (undefined === method || null === method || 0 === method.getParameterCount()) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const parameters = method.getParameters();
|
||||||
|
const results: string[] = [];
|
||||||
|
for (let indexI = 0; indexI < parameters.length; indexI++) {
|
||||||
|
const paramType = parameters[indexI].getType();
|
||||||
|
results.push(paramType.name);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private converParams(params: string[], paramTypes: string[]): any[] {
|
||||||
|
const results: any[] = [];
|
||||||
|
|
||||||
|
if (undefined === params || null === params || 0 === params.length) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
if (undefined === paramTypes || null === paramTypes || 0 === paramTypes.length) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
if (params.length !== paramTypes.length) {
|
||||||
|
throw new SubscriberParameterError(`Count is not same from server[${params.length}] and method[${paramTypes.length}]`);
|
||||||
|
}
|
||||||
|
for (let indexI = 0; indexI < params.length; indexI++) {
|
||||||
|
const param = params[indexI];
|
||||||
|
const type = paramTypes[indexI];
|
||||||
|
switch (type) {
|
||||||
|
case 'Object':
|
||||||
|
case 'Array':
|
||||||
|
case 'Map':
|
||||||
|
results.push(JSON.parse(param));
|
||||||
|
break;
|
||||||
|
case 'String':
|
||||||
|
results.push(param);
|
||||||
|
break;
|
||||||
|
case 'Number':
|
||||||
|
results.push(Number(param));
|
||||||
|
break;
|
||||||
|
case 'Boolean':
|
||||||
|
results.push(Boolean(param));
|
||||||
|
break;
|
||||||
|
case 'Function':
|
||||||
|
throw new SubscriberParameterError(`Function type [${indexI}] is not allowed`);
|
||||||
|
default:
|
||||||
|
throw new SubscriberParameterError(`${type} type parameter[${indexI}] is not allowed`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
17
projects/loafer/ng-rpc/src/public_api.ts
Normal file
17
projects/loafer/ng-rpc/src/public_api.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Public API Surface of ng-rpc
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './lib/client/RPCClient';
|
||||||
|
export * from './lib/client/RPCClientRWC';
|
||||||
|
export * from './lib/client/rwc/websocket/RPCClientWebsocketRWC';
|
||||||
|
export * from './lib/client/rwc/websocket/RxWebsocketSubject';
|
||||||
|
export * from './lib/core/error';
|
||||||
|
export * from './lib/core/token';
|
||||||
|
export * from './lib/decorator/rpc-subscriber.decorator';
|
||||||
|
export * from './lib/protocol/RPCClientCodec';
|
||||||
|
export * from './lib/protocol/RPCError';
|
||||||
|
export * from './lib/protocol/json/JSONRPCClientCodec';
|
||||||
|
export * from './lib/service/rpc.service';
|
||||||
|
export * from './lib/subscribe/subscribe.service';
|
||||||
|
export * from './lib/ng-rpc.module';
|
22
projects/loafer/ng-rpc/src/test.ts
Normal file
22
projects/loafer/ng-rpc/src/test.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||||
|
|
||||||
|
import 'core-js/es7/reflect';
|
||||||
|
import 'zone.js/dist/zone';
|
||||||
|
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);
|
33
projects/loafer/ng-rpc/tsconfig.lib.json
Normal file
33
projects/loafer/ng-rpc/tsconfig.lib.json
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../../out-tsc/lib",
|
||||||
|
"target": "es2015",
|
||||||
|
"module": "es2015",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"declaration": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"inlineSources": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"types": [],
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es2015"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"annotateForClosureCompiler": true,
|
||||||
|
"skipTemplateCodegen": true,
|
||||||
|
"strictMetadataEmit": true,
|
||||||
|
"fullTemplateTypeCheck": true,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"flatModuleId": "AUTOGENERATED",
|
||||||
|
"flatModuleOutFile": "AUTOGENERATED"
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"src/test.ts",
|
||||||
|
"**/*.spec.ts"
|
||||||
|
]
|
||||||
|
}
|
17
projects/loafer/ng-rpc/tsconfig.spec.json
Normal file
17
projects/loafer/ng-rpc/tsconfig.spec.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../../out-tsc/spec",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/test.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
17
projects/loafer/ng-rpc/tslint.json
Normal file
17
projects/loafer/ng-rpc/tslint.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../tslint.json",
|
||||||
|
"rules": {
|
||||||
|
"directive-selector": [
|
||||||
|
true,
|
||||||
|
"attribute",
|
||||||
|
"lib",
|
||||||
|
"camelCase"
|
||||||
|
],
|
||||||
|
"component-selector": [
|
||||||
|
true,
|
||||||
|
"element",
|
||||||
|
"lib",
|
||||||
|
"kebab-case"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
31
tsconfig.json
Normal file
31
tsconfig.json
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "./",
|
||||||
|
"outDir": "./dist/out-tsc",
|
||||||
|
"sourceMap": true,
|
||||||
|
"declaration": false,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"target": "es5",
|
||||||
|
"typeRoots": [
|
||||||
|
"node_modules/@types"
|
||||||
|
],
|
||||||
|
"lib": [
|
||||||
|
"es2017",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@loafer/ng-logger": [
|
||||||
|
"dist/loafer/ng-logger"
|
||||||
|
],
|
||||||
|
"@loafer/ng-rest": [
|
||||||
|
"dist/loafer/ng-rest"
|
||||||
|
],
|
||||||
|
"@loafer/ng-rpc": [
|
||||||
|
"dist/loafer/ng-rpc"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
130
tslint.json
Normal file
130
tslint.json
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
{
|
||||||
|
"rulesDirectory": [
|
||||||
|
"node_modules/codelyzer"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"arrow-return-shorthand": true,
|
||||||
|
"callable-types": true,
|
||||||
|
"class-name": true,
|
||||||
|
"comment-format": [
|
||||||
|
true,
|
||||||
|
"check-space"
|
||||||
|
],
|
||||||
|
"curly": true,
|
||||||
|
"deprecation": {
|
||||||
|
"severity": "warn"
|
||||||
|
},
|
||||||
|
"eofline": true,
|
||||||
|
"forin": true,
|
||||||
|
"import-blacklist": [
|
||||||
|
true,
|
||||||
|
"rxjs/Rx"
|
||||||
|
],
|
||||||
|
"import-spacing": true,
|
||||||
|
"indent": [
|
||||||
|
true,
|
||||||
|
"spaces"
|
||||||
|
],
|
||||||
|
"interface-over-type-literal": true,
|
||||||
|
"label-position": true,
|
||||||
|
"max-line-length": [
|
||||||
|
true,
|
||||||
|
140
|
||||||
|
],
|
||||||
|
"member-access": false,
|
||||||
|
"member-ordering": [
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
"order": [
|
||||||
|
"static-field",
|
||||||
|
"instance-field",
|
||||||
|
"static-method",
|
||||||
|
"instance-method"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no-arg": true,
|
||||||
|
"no-bitwise": true,
|
||||||
|
"no-console": [
|
||||||
|
true,
|
||||||
|
"debug",
|
||||||
|
"info",
|
||||||
|
"time",
|
||||||
|
"timeEnd",
|
||||||
|
"trace"
|
||||||
|
],
|
||||||
|
"no-construct": true,
|
||||||
|
"no-debugger": true,
|
||||||
|
"no-duplicate-super": true,
|
||||||
|
"no-empty": false,
|
||||||
|
"no-empty-interface": true,
|
||||||
|
"no-eval": true,
|
||||||
|
"no-inferrable-types": [
|
||||||
|
true,
|
||||||
|
"ignore-params"
|
||||||
|
],
|
||||||
|
"no-misused-new": true,
|
||||||
|
"no-non-null-assertion": true,
|
||||||
|
"no-shadowed-variable": true,
|
||||||
|
"no-string-literal": false,
|
||||||
|
"no-string-throw": true,
|
||||||
|
"no-switch-case-fall-through": true,
|
||||||
|
"no-trailing-whitespace": true,
|
||||||
|
"no-unnecessary-initializer": true,
|
||||||
|
"no-unused-expression": true,
|
||||||
|
"no-use-before-declare": true,
|
||||||
|
"no-var-keyword": true,
|
||||||
|
"object-literal-sort-keys": false,
|
||||||
|
"one-line": [
|
||||||
|
true,
|
||||||
|
"check-open-brace",
|
||||||
|
"check-catch",
|
||||||
|
"check-else",
|
||||||
|
"check-whitespace"
|
||||||
|
],
|
||||||
|
"prefer-const": true,
|
||||||
|
"quotemark": [
|
||||||
|
true,
|
||||||
|
"single"
|
||||||
|
],
|
||||||
|
"radix": true,
|
||||||
|
"semicolon": [
|
||||||
|
true,
|
||||||
|
"always"
|
||||||
|
],
|
||||||
|
"triple-equals": [
|
||||||
|
true,
|
||||||
|
"allow-null-check"
|
||||||
|
],
|
||||||
|
"typedef-whitespace": [
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
"call-signature": "nospace",
|
||||||
|
"index-signature": "nospace",
|
||||||
|
"parameter": "nospace",
|
||||||
|
"property-declaration": "nospace",
|
||||||
|
"variable-declaration": "nospace"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"unified-signatures": true,
|
||||||
|
"variable-name": false,
|
||||||
|
"whitespace": [
|
||||||
|
true,
|
||||||
|
"check-branch",
|
||||||
|
"check-decl",
|
||||||
|
"check-operator",
|
||||||
|
"check-separator",
|
||||||
|
"check-type"
|
||||||
|
],
|
||||||
|
"no-output-on-prefix": true,
|
||||||
|
"use-input-property-decorator": true,
|
||||||
|
"use-output-property-decorator": true,
|
||||||
|
"use-host-property-decorator": true,
|
||||||
|
"no-input-rename": true,
|
||||||
|
"no-output-rename": true,
|
||||||
|
"use-life-cycle-interface": true,
|
||||||
|
"use-pipe-transform-interface": true,
|
||||||
|
"component-class-suffix": true,
|
||||||
|
"directive-class-suffix": true
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user