├── .circleci └── config.yml ├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── dist ├── amd │ ├── async-binding.d.ts │ ├── async-binding.js │ ├── aurelia-async-binding.d.ts │ └── aurelia-async-binding.js ├── commonjs │ ├── async-binding.d.ts │ ├── async-binding.js │ ├── aurelia-async-binding.d.ts │ └── aurelia-async-binding.js ├── es2015 │ ├── async-binding.d.ts │ ├── async-binding.js │ ├── aurelia-async-binding.d.ts │ └── aurelia-async-binding.js ├── native-modules │ ├── async-binding.d.ts │ ├── async-binding.js │ ├── aurelia-async-binding.d.ts │ └── aurelia-async-binding.js └── system │ ├── async-binding.d.ts │ ├── async-binding.js │ ├── aurelia-async-binding.d.ts │ └── aurelia-async-binding.js ├── package-lock.json ├── package.json ├── src ├── async-binding.ts └── aurelia-async-binding.ts ├── test ├── jest-css-stub.js ├── jest-pretest.ts └── unit │ ├── async-binding.spec.ts │ └── mocks │ ├── async-binding-vm.html │ └── async-binding-vm.ts ├── tsconfig.json └── tslint.json /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | test: 4 | working_directory: ~/repo 5 | docker: 6 | - image: circleci/node:9-jessie-browsers 7 | steps: 8 | - checkout 9 | - run: npm install 10 | - run: 11 | name: Tests 12 | command: 'npm run test-ci' 13 | 14 | workflows: 15 | version: 2 16 | build_and_test: 17 | jobs: 18 | - test: 19 | filters: 20 | branches: 21 | only: master 22 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = crlf 9 | insert_final_newline = true 10 | 11 | # 4 space indentation 12 | [**.*] 13 | indent_style = space 14 | indent_size = 2 15 | 16 | [*.{json}] 17 | indent_size = 2 18 | 19 | [node_modules/**/*,dist/**/*] 20 | insert_final_newline = false 21 | indent_style = none 22 | indent_size = none 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | test/coverage-jest/ 4 | .vscode 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Vildan Softic 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aurelia-async-binding 2 | 3 | [![npm Version](https://img.shields.io/npm/v/aurelia-async-binding.svg)](https://www.npmjs.com/package/aurelia-async-binding) 4 | [![Join the chat at https://gitter.im/aurelia/discuss](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/aurelia/discuss?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | [![CircleCI](https://circleci.com/gh/zewa666/aurelia-async-binding.svg?style=shield)](https://circleci.com/gh/zewa666/aurelia-async-binding) 6 | [![Coverage Status](https://coveralls.io/repos/github/zewa666/aurelia-async-binding/badge.svg?branch=master)](https://coveralls.io/github/zewa666/aurelia-async-binding?branch=master) 7 | 8 | An Aurelia binding behavior to consume async streams and promises directly from within your templates. 9 | 10 | ## Install 11 | Install the npm dependency via 12 | 13 | ```bash 14 | npm install aurelia-async-binding 15 | ``` 16 | 17 | ## Configuration 18 | In your `main.ts` you'll have to register the plugin which makes it globally available: 19 | 20 | ```typescript 21 | import {Aurelia} from 'aurelia-framework' 22 | import environment from './environment'; 23 | 24 | export function configure(aurelia: Aurelia) { 25 | aurelia.use 26 | .standardConfiguration() 27 | .feature('resources'); 28 | 29 | ... 30 | 31 | aurelia.use.plugin("aurelia-async-binding"); // <----- REGISTER THE PLUGIN 32 | 33 | aurelia.start().then(() => aurelia.setRoot()); 34 | } 35 | ``` 36 | 37 | ## Features 38 | * Easily access streamed values 39 | * Pluck complex object properties 40 | * Deep-plucking to access nested complex object properties using the dot-notation 41 | * Register `completedHandler` for once the stream completes 42 | * Register `error` handlers to react on streamed errors 43 | 44 | 45 | ## Usage 46 | Once the plugin is installed and configured you can use the `async` binding behavior. 47 | An example VM and View can be seen below: 48 | 49 | ```typescript 50 | import { Observable } from 'rxjs/Observable'; 51 | import "rxjs/add/operator/map"; 52 | import "rxjs/add/operator/take"; 53 | import "rxjs/add/observable/interval"; 54 | import "rxjs/add/observable/of"; 55 | import "rxjs/add/observable/from"; 56 | 57 | interface SPAFramework { 58 | label: string; 59 | url: string; 60 | } 61 | export class App { 62 | public frameworks: Observable; 63 | public frameworkOverTime: Observable; 64 | public isSequenceDone: boolean = false; 65 | 66 | constructor() { 67 | const data: SPAFramework[] = [ 68 | { label: "Aurelia", url: "http://aurelia.io" }, 69 | { label: "Angular v4", url: "http://angular.io" }, 70 | { label: "React", url: "https://facebook.github.io/react/" }, 71 | ]; 72 | 73 | this.frameworks = Observable.of(data); 74 | 75 | this.frameworkOverTime = Observable.interval(2000) 76 | .map((idx) => data[idx]) 77 | .take(data.length); 78 | } 79 | 80 | public completedHandler = () => { 81 | setTimeout(() => this.isSequenceDone = true, 2000); 82 | } 83 | } 84 | ``` 85 | 86 | ```html 87 | 106 | 107 | ``` 108 | 109 | ## Acknowledgement 110 | Thanks goes to Dwayne Charrington for his Aurelia-TypeScript starter package https://github.com/Vheissu/aurelia-typescript-plugin 111 | -------------------------------------------------------------------------------- /dist/amd/async-binding.d.ts: -------------------------------------------------------------------------------- 1 | import { Subscription } from "rxjs"; 2 | import { Binding } from "aurelia-binding"; 3 | export interface AsyncAureliaBinding extends Binding { 4 | originalupdateTarget(value: any): void; 5 | _subscription?: Subscription; 6 | } 7 | export interface AsyncBindingBehaviorOptions { 8 | catch: any; 9 | completed: () => void; 10 | error: any; 11 | property: string; 12 | } 13 | export declare class asyncBindingBehavior { 14 | getPropByPath(obj: any, keyPath: string): any; 15 | bind(binding: AsyncAureliaBinding, _source: string, options?: AsyncBindingBehaviorOptions): void; 16 | unbind(binding: AsyncAureliaBinding): void; 17 | } 18 | -------------------------------------------------------------------------------- /dist/amd/async-binding.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | define(["require", "exports", "rxjs", "aurelia-framework"], function (require, exports, rxjs_1, aurelia_framework_1) { 8 | "use strict"; 9 | Object.defineProperty(exports, "__esModule", { value: true }); 10 | exports.asyncBindingBehavior = void 0; 11 | var asyncBindingBehavior = /** @class */ (function () { 12 | function asyncBindingBehavior() { 13 | } 14 | asyncBindingBehavior.prototype.getPropByPath = function (obj, keyPath) { 15 | return keyPath 16 | .split(".") 17 | .reduce(function (prev, curr) { return prev[curr]; }, obj); 18 | }; 19 | asyncBindingBehavior.prototype.bind = function (binding, _source, options) { 20 | var _this = this; 21 | binding.originalupdateTarget = binding.updateTarget || (function () { }); 22 | binding.updateTarget = function (a) { 23 | if (binding._subscription && 24 | typeof binding._subscription.unsubscribe === "function") { 25 | binding._subscription.unsubscribe(); 26 | } 27 | if (a && typeof a.then === "function") { 28 | a.then(function (res) { return binding.originalupdateTarget(options && options.property ? _this.getPropByPath(res, options.property) : res); }); 29 | if (options && options.catch) { 30 | a.catch(function (res) { return typeof options.catch === "function" 31 | ? options.catch(res) 32 | : binding.originalupdateTarget(options.catch); }); 33 | } 34 | } 35 | else if (a instanceof rxjs_1.Observable) { 36 | var error = options 37 | ? typeof options.error === "function" 38 | ? options.error 39 | : function () { binding.originalupdateTarget(options && options.property ? _this.getPropByPath(options.error, options.property) : options.error); } 40 | : undefined; 41 | binding._subscription = a.subscribe(function (res) { 42 | binding.originalupdateTarget(options && options.property ? _this.getPropByPath(res, options.property) : res); 43 | }, error, options ? options.completed : undefined); 44 | } 45 | else { 46 | binding.originalupdateTarget(a); 47 | } 48 | }; 49 | }; 50 | asyncBindingBehavior.prototype.unbind = function (binding) { 51 | binding.updateTarget = binding.originalupdateTarget; 52 | binding.originalupdateTarget = undefined; 53 | if (binding._subscription && 54 | typeof binding._subscription.unsubscribe === "function") { 55 | binding._subscription.unsubscribe(); 56 | } 57 | }; 58 | asyncBindingBehavior = __decorate([ 59 | (0, aurelia_framework_1.bindingBehavior)("async") 60 | ], asyncBindingBehavior); 61 | return asyncBindingBehavior; 62 | }()); 63 | exports.asyncBindingBehavior = asyncBindingBehavior; 64 | }); 65 | -------------------------------------------------------------------------------- /dist/amd/aurelia-async-binding.d.ts: -------------------------------------------------------------------------------- 1 | import { FrameworkConfiguration } from "aurelia-framework"; 2 | export declare function configure(aurelia: FrameworkConfiguration): void; 3 | export * from "./async-binding"; 4 | -------------------------------------------------------------------------------- /dist/amd/aurelia-async-binding.js: -------------------------------------------------------------------------------- 1 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 2 | if (k2 === undefined) k2 = k; 3 | var desc = Object.getOwnPropertyDescriptor(m, k); 4 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 5 | desc = { enumerable: true, get: function() { return m[k]; } }; 6 | } 7 | Object.defineProperty(o, k2, desc); 8 | }) : (function(o, m, k, k2) { 9 | if (k2 === undefined) k2 = k; 10 | o[k2] = m[k]; 11 | })); 12 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 13 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 14 | }; 15 | define(["require", "exports", "aurelia-pal", "./async-binding"], function (require, exports, aurelia_pal_1, async_binding_1) { 16 | "use strict"; 17 | Object.defineProperty(exports, "__esModule", { value: true }); 18 | exports.configure = void 0; 19 | function configure(aurelia) { 20 | aurelia.globalResources([ 21 | aurelia_pal_1.PLATFORM.moduleName("./async-binding") 22 | ]); 23 | } 24 | exports.configure = configure; 25 | __exportStar(async_binding_1, exports); 26 | }); 27 | -------------------------------------------------------------------------------- /dist/commonjs/async-binding.d.ts: -------------------------------------------------------------------------------- 1 | import { Subscription } from "rxjs"; 2 | import { Binding } from "aurelia-binding"; 3 | export interface AsyncAureliaBinding extends Binding { 4 | originalupdateTarget(value: any): void; 5 | _subscription?: Subscription; 6 | } 7 | export interface AsyncBindingBehaviorOptions { 8 | catch: any; 9 | completed: () => void; 10 | error: any; 11 | property: string; 12 | } 13 | export declare class asyncBindingBehavior { 14 | getPropByPath(obj: any, keyPath: string): any; 15 | bind(binding: AsyncAureliaBinding, _source: string, options?: AsyncBindingBehaviorOptions): void; 16 | unbind(binding: AsyncAureliaBinding): void; 17 | } 18 | -------------------------------------------------------------------------------- /dist/commonjs/async-binding.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 3 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 4 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 5 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 6 | return c > 3 && r && Object.defineProperty(target, key, r), r; 7 | }; 8 | Object.defineProperty(exports, "__esModule", { value: true }); 9 | exports.asyncBindingBehavior = void 0; 10 | var rxjs_1 = require("rxjs"); 11 | var aurelia_framework_1 = require("aurelia-framework"); 12 | var asyncBindingBehavior = /** @class */ (function () { 13 | function asyncBindingBehavior() { 14 | } 15 | asyncBindingBehavior.prototype.getPropByPath = function (obj, keyPath) { 16 | return keyPath 17 | .split(".") 18 | .reduce(function (prev, curr) { return prev[curr]; }, obj); 19 | }; 20 | asyncBindingBehavior.prototype.bind = function (binding, _source, options) { 21 | var _this = this; 22 | binding.originalupdateTarget = binding.updateTarget || (function () { }); 23 | binding.updateTarget = function (a) { 24 | if (binding._subscription && 25 | typeof binding._subscription.unsubscribe === "function") { 26 | binding._subscription.unsubscribe(); 27 | } 28 | if (a && typeof a.then === "function") { 29 | a.then(function (res) { return binding.originalupdateTarget(options && options.property ? _this.getPropByPath(res, options.property) : res); }); 30 | if (options && options.catch) { 31 | a.catch(function (res) { return typeof options.catch === "function" 32 | ? options.catch(res) 33 | : binding.originalupdateTarget(options.catch); }); 34 | } 35 | } 36 | else if (a instanceof rxjs_1.Observable) { 37 | var error = options 38 | ? typeof options.error === "function" 39 | ? options.error 40 | : function () { binding.originalupdateTarget(options && options.property ? _this.getPropByPath(options.error, options.property) : options.error); } 41 | : undefined; 42 | binding._subscription = a.subscribe(function (res) { 43 | binding.originalupdateTarget(options && options.property ? _this.getPropByPath(res, options.property) : res); 44 | }, error, options ? options.completed : undefined); 45 | } 46 | else { 47 | binding.originalupdateTarget(a); 48 | } 49 | }; 50 | }; 51 | asyncBindingBehavior.prototype.unbind = function (binding) { 52 | binding.updateTarget = binding.originalupdateTarget; 53 | binding.originalupdateTarget = undefined; 54 | if (binding._subscription && 55 | typeof binding._subscription.unsubscribe === "function") { 56 | binding._subscription.unsubscribe(); 57 | } 58 | }; 59 | asyncBindingBehavior = __decorate([ 60 | (0, aurelia_framework_1.bindingBehavior)("async") 61 | ], asyncBindingBehavior); 62 | return asyncBindingBehavior; 63 | }()); 64 | exports.asyncBindingBehavior = asyncBindingBehavior; 65 | -------------------------------------------------------------------------------- /dist/commonjs/aurelia-async-binding.d.ts: -------------------------------------------------------------------------------- 1 | import { FrameworkConfiguration } from "aurelia-framework"; 2 | export declare function configure(aurelia: FrameworkConfiguration): void; 3 | export * from "./async-binding"; 4 | -------------------------------------------------------------------------------- /dist/commonjs/aurelia-async-binding.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 15 | }; 16 | Object.defineProperty(exports, "__esModule", { value: true }); 17 | exports.configure = void 0; 18 | var aurelia_pal_1 = require("aurelia-pal"); 19 | function configure(aurelia) { 20 | aurelia.globalResources([ 21 | aurelia_pal_1.PLATFORM.moduleName("./async-binding") 22 | ]); 23 | } 24 | exports.configure = configure; 25 | __exportStar(require("./async-binding"), exports); 26 | -------------------------------------------------------------------------------- /dist/es2015/async-binding.d.ts: -------------------------------------------------------------------------------- 1 | import { Subscription } from "rxjs"; 2 | import { Binding } from "aurelia-binding"; 3 | export interface AsyncAureliaBinding extends Binding { 4 | originalupdateTarget(value: any): void; 5 | _subscription?: Subscription; 6 | } 7 | export interface AsyncBindingBehaviorOptions { 8 | catch: any; 9 | completed: () => void; 10 | error: any; 11 | property: string; 12 | } 13 | export declare class asyncBindingBehavior { 14 | getPropByPath(obj: any, keyPath: string): any; 15 | bind(binding: AsyncAureliaBinding, _source: string, options?: AsyncBindingBehaviorOptions): void; 16 | unbind(binding: AsyncAureliaBinding): void; 17 | } 18 | -------------------------------------------------------------------------------- /dist/es2015/async-binding.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { Observable } from "rxjs"; 8 | import { bindingBehavior } from "aurelia-framework"; 9 | var asyncBindingBehavior = /** @class */ (function () { 10 | function asyncBindingBehavior() { 11 | } 12 | asyncBindingBehavior.prototype.getPropByPath = function (obj, keyPath) { 13 | return keyPath 14 | .split(".") 15 | .reduce(function (prev, curr) { return prev[curr]; }, obj); 16 | }; 17 | asyncBindingBehavior.prototype.bind = function (binding, _source, options) { 18 | var _this = this; 19 | binding.originalupdateTarget = binding.updateTarget || (function () { }); 20 | binding.updateTarget = function (a) { 21 | if (binding._subscription && 22 | typeof binding._subscription.unsubscribe === "function") { 23 | binding._subscription.unsubscribe(); 24 | } 25 | if (a && typeof a.then === "function") { 26 | a.then(function (res) { return binding.originalupdateTarget(options && options.property ? _this.getPropByPath(res, options.property) : res); }); 27 | if (options && options.catch) { 28 | a.catch(function (res) { return typeof options.catch === "function" 29 | ? options.catch(res) 30 | : binding.originalupdateTarget(options.catch); }); 31 | } 32 | } 33 | else if (a instanceof Observable) { 34 | var error = options 35 | ? typeof options.error === "function" 36 | ? options.error 37 | : function () { binding.originalupdateTarget(options && options.property ? _this.getPropByPath(options.error, options.property) : options.error); } 38 | : undefined; 39 | binding._subscription = a.subscribe(function (res) { 40 | binding.originalupdateTarget(options && options.property ? _this.getPropByPath(res, options.property) : res); 41 | }, error, options ? options.completed : undefined); 42 | } 43 | else { 44 | binding.originalupdateTarget(a); 45 | } 46 | }; 47 | }; 48 | asyncBindingBehavior.prototype.unbind = function (binding) { 49 | binding.updateTarget = binding.originalupdateTarget; 50 | binding.originalupdateTarget = undefined; 51 | if (binding._subscription && 52 | typeof binding._subscription.unsubscribe === "function") { 53 | binding._subscription.unsubscribe(); 54 | } 55 | }; 56 | asyncBindingBehavior = __decorate([ 57 | bindingBehavior("async") 58 | ], asyncBindingBehavior); 59 | return asyncBindingBehavior; 60 | }()); 61 | export { asyncBindingBehavior }; 62 | -------------------------------------------------------------------------------- /dist/es2015/aurelia-async-binding.d.ts: -------------------------------------------------------------------------------- 1 | import { FrameworkConfiguration } from "aurelia-framework"; 2 | export declare function configure(aurelia: FrameworkConfiguration): void; 3 | export * from "./async-binding"; 4 | -------------------------------------------------------------------------------- /dist/es2015/aurelia-async-binding.js: -------------------------------------------------------------------------------- 1 | import { PLATFORM } from "aurelia-pal"; 2 | export function configure(aurelia) { 3 | aurelia.globalResources([ 4 | PLATFORM.moduleName("./async-binding") 5 | ]); 6 | } 7 | export * from "./async-binding"; 8 | -------------------------------------------------------------------------------- /dist/native-modules/async-binding.d.ts: -------------------------------------------------------------------------------- 1 | import { Subscription } from "rxjs"; 2 | import { Binding } from "aurelia-binding"; 3 | export interface AsyncAureliaBinding extends Binding { 4 | originalupdateTarget(value: any): void; 5 | _subscription?: Subscription; 6 | } 7 | export interface AsyncBindingBehaviorOptions { 8 | catch: any; 9 | completed: () => void; 10 | error: any; 11 | property: string; 12 | } 13 | export declare class asyncBindingBehavior { 14 | getPropByPath(obj: any, keyPath: string): any; 15 | bind(binding: AsyncAureliaBinding, _source: string, options?: AsyncBindingBehaviorOptions): void; 16 | unbind(binding: AsyncAureliaBinding): void; 17 | } 18 | -------------------------------------------------------------------------------- /dist/native-modules/async-binding.js: -------------------------------------------------------------------------------- 1 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 2 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 3 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 4 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 5 | return c > 3 && r && Object.defineProperty(target, key, r), r; 6 | }; 7 | import { Observable } from "rxjs"; 8 | import { bindingBehavior } from "aurelia-framework"; 9 | var asyncBindingBehavior = /** @class */ (function () { 10 | function asyncBindingBehavior() { 11 | } 12 | asyncBindingBehavior.prototype.getPropByPath = function (obj, keyPath) { 13 | return keyPath 14 | .split(".") 15 | .reduce(function (prev, curr) { return prev[curr]; }, obj); 16 | }; 17 | asyncBindingBehavior.prototype.bind = function (binding, _source, options) { 18 | var _this = this; 19 | binding.originalupdateTarget = binding.updateTarget || (function () { }); 20 | binding.updateTarget = function (a) { 21 | if (binding._subscription && 22 | typeof binding._subscription.unsubscribe === "function") { 23 | binding._subscription.unsubscribe(); 24 | } 25 | if (a && typeof a.then === "function") { 26 | a.then(function (res) { return binding.originalupdateTarget(options && options.property ? _this.getPropByPath(res, options.property) : res); }); 27 | if (options && options.catch) { 28 | a.catch(function (res) { return typeof options.catch === "function" 29 | ? options.catch(res) 30 | : binding.originalupdateTarget(options.catch); }); 31 | } 32 | } 33 | else if (a instanceof Observable) { 34 | var error = options 35 | ? typeof options.error === "function" 36 | ? options.error 37 | : function () { binding.originalupdateTarget(options && options.property ? _this.getPropByPath(options.error, options.property) : options.error); } 38 | : undefined; 39 | binding._subscription = a.subscribe(function (res) { 40 | binding.originalupdateTarget(options && options.property ? _this.getPropByPath(res, options.property) : res); 41 | }, error, options ? options.completed : undefined); 42 | } 43 | else { 44 | binding.originalupdateTarget(a); 45 | } 46 | }; 47 | }; 48 | asyncBindingBehavior.prototype.unbind = function (binding) { 49 | binding.updateTarget = binding.originalupdateTarget; 50 | binding.originalupdateTarget = undefined; 51 | if (binding._subscription && 52 | typeof binding._subscription.unsubscribe === "function") { 53 | binding._subscription.unsubscribe(); 54 | } 55 | }; 56 | asyncBindingBehavior = __decorate([ 57 | bindingBehavior("async") 58 | ], asyncBindingBehavior); 59 | return asyncBindingBehavior; 60 | }()); 61 | export { asyncBindingBehavior }; 62 | -------------------------------------------------------------------------------- /dist/native-modules/aurelia-async-binding.d.ts: -------------------------------------------------------------------------------- 1 | import { FrameworkConfiguration } from "aurelia-framework"; 2 | export declare function configure(aurelia: FrameworkConfiguration): void; 3 | export * from "./async-binding"; 4 | -------------------------------------------------------------------------------- /dist/native-modules/aurelia-async-binding.js: -------------------------------------------------------------------------------- 1 | import { PLATFORM } from "aurelia-pal"; 2 | export function configure(aurelia) { 3 | aurelia.globalResources([ 4 | PLATFORM.moduleName("./async-binding") 5 | ]); 6 | } 7 | export * from "./async-binding"; 8 | -------------------------------------------------------------------------------- /dist/system/async-binding.d.ts: -------------------------------------------------------------------------------- 1 | import { Subscription } from "rxjs"; 2 | import { Binding } from "aurelia-binding"; 3 | export interface AsyncAureliaBinding extends Binding { 4 | originalupdateTarget(value: any): void; 5 | _subscription?: Subscription; 6 | } 7 | export interface AsyncBindingBehaviorOptions { 8 | catch: any; 9 | completed: () => void; 10 | error: any; 11 | property: string; 12 | } 13 | export declare class asyncBindingBehavior { 14 | getPropByPath(obj: any, keyPath: string): any; 15 | bind(binding: AsyncAureliaBinding, _source: string, options?: AsyncBindingBehaviorOptions): void; 16 | unbind(binding: AsyncAureliaBinding): void; 17 | } 18 | -------------------------------------------------------------------------------- /dist/system/async-binding.js: -------------------------------------------------------------------------------- 1 | System.register(["rxjs", "aurelia-framework"], function (exports_1, context_1) { 2 | "use strict"; 3 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { 4 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; 5 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 6 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; 7 | return c > 3 && r && Object.defineProperty(target, key, r), r; 8 | }; 9 | var rxjs_1, aurelia_framework_1, asyncBindingBehavior; 10 | var __moduleName = context_1 && context_1.id; 11 | return { 12 | setters: [ 13 | function (rxjs_1_1) { 14 | rxjs_1 = rxjs_1_1; 15 | }, 16 | function (aurelia_framework_1_1) { 17 | aurelia_framework_1 = aurelia_framework_1_1; 18 | } 19 | ], 20 | execute: function () { 21 | asyncBindingBehavior = /** @class */ (function () { 22 | function asyncBindingBehavior() { 23 | } 24 | asyncBindingBehavior.prototype.getPropByPath = function (obj, keyPath) { 25 | return keyPath 26 | .split(".") 27 | .reduce(function (prev, curr) { return prev[curr]; }, obj); 28 | }; 29 | asyncBindingBehavior.prototype.bind = function (binding, _source, options) { 30 | var _this = this; 31 | binding.originalupdateTarget = binding.updateTarget || (function () { }); 32 | binding.updateTarget = function (a) { 33 | if (binding._subscription && 34 | typeof binding._subscription.unsubscribe === "function") { 35 | binding._subscription.unsubscribe(); 36 | } 37 | if (a && typeof a.then === "function") { 38 | a.then(function (res) { return binding.originalupdateTarget(options && options.property ? _this.getPropByPath(res, options.property) : res); }); 39 | if (options && options.catch) { 40 | a.catch(function (res) { return typeof options.catch === "function" 41 | ? options.catch(res) 42 | : binding.originalupdateTarget(options.catch); }); 43 | } 44 | } 45 | else if (a instanceof rxjs_1.Observable) { 46 | var error = options 47 | ? typeof options.error === "function" 48 | ? options.error 49 | : function () { binding.originalupdateTarget(options && options.property ? _this.getPropByPath(options.error, options.property) : options.error); } 50 | : undefined; 51 | binding._subscription = a.subscribe(function (res) { 52 | binding.originalupdateTarget(options && options.property ? _this.getPropByPath(res, options.property) : res); 53 | }, error, options ? options.completed : undefined); 54 | } 55 | else { 56 | binding.originalupdateTarget(a); 57 | } 58 | }; 59 | }; 60 | asyncBindingBehavior.prototype.unbind = function (binding) { 61 | binding.updateTarget = binding.originalupdateTarget; 62 | binding.originalupdateTarget = undefined; 63 | if (binding._subscription && 64 | typeof binding._subscription.unsubscribe === "function") { 65 | binding._subscription.unsubscribe(); 66 | } 67 | }; 68 | asyncBindingBehavior = __decorate([ 69 | aurelia_framework_1.bindingBehavior("async") 70 | ], asyncBindingBehavior); 71 | return asyncBindingBehavior; 72 | }()); 73 | exports_1("asyncBindingBehavior", asyncBindingBehavior); 74 | } 75 | }; 76 | }); 77 | -------------------------------------------------------------------------------- /dist/system/aurelia-async-binding.d.ts: -------------------------------------------------------------------------------- 1 | import { FrameworkConfiguration } from "aurelia-framework"; 2 | export declare function configure(aurelia: FrameworkConfiguration): void; 3 | export * from "./async-binding"; 4 | -------------------------------------------------------------------------------- /dist/system/aurelia-async-binding.js: -------------------------------------------------------------------------------- 1 | System.register(["aurelia-pal", "./async-binding"], function (exports_1, context_1) { 2 | "use strict"; 3 | var aurelia_pal_1; 4 | var __moduleName = context_1 && context_1.id; 5 | function configure(aurelia) { 6 | aurelia.globalResources([ 7 | aurelia_pal_1.PLATFORM.moduleName("./async-binding") 8 | ]); 9 | } 10 | exports_1("configure", configure); 11 | var exportedNames_1 = { 12 | "configure": true 13 | }; 14 | function exportStar_1(m) { 15 | var exports = {}; 16 | for (var n in m) { 17 | if (n !== "default" && !exportedNames_1.hasOwnProperty(n)) exports[n] = m[n]; 18 | } 19 | exports_1(exports); 20 | } 21 | return { 22 | setters: [ 23 | function (aurelia_pal_1_1) { 24 | aurelia_pal_1 = aurelia_pal_1_1; 25 | }, 26 | function (async_binding_1_1) { 27 | exportStar_1(async_binding_1_1); 28 | } 29 | ], 30 | execute: function () { 31 | } 32 | }; 33 | }); 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aurelia-async-binding", 3 | "version": "2.0.1", 4 | "description": "Aurelia async bindingbehavior to consume Observables and Promises", 5 | "keywords": [ 6 | "rxjs", 7 | "bindingbehavior", 8 | "async", 9 | "aurelia" 10 | ], 11 | "main": "dist/commonjs/aurelia-async-binding.js", 12 | "typings": "dist/commonjs/aurelia-async-binding.d.ts", 13 | "scripts": { 14 | "lint": "cross-env tslint --project tsconfig.json", 15 | "pretest": "cross-env npm run lint", 16 | "test": "cross-env jest", 17 | "test-watch": "cross-env jest --watch", 18 | "test-ci": "cross-env jest && cat ./test/coverage-jest/lcov.info | ./node_modules/coveralls/bin/coveralls.js", 19 | "build:amd": "cross-env tsc --outDir dist/amd --module amd", 20 | "build:commonjs": "cross-env tsc --outDir dist/commonjs --module commonjs", 21 | "build:es2015": "cross-env tsc --outDir dist/es2015 --module es2015", 22 | "build:native-modules": "cross-env tsc --outDir dist/native-modules --module es2015", 23 | "build:system": "cross-env tsc --outDir dist/system --module system", 24 | "prebuild": "cross-env rimraf dist", 25 | "build": "concurrently \"npm run build:amd\" \"npm run build:commonjs\" \"npm run build:es2015\" \"npm run build:native-modules\" \"npm run build:system\"" 26 | }, 27 | "jest": { 28 | "modulePaths": [ 29 | "/src", 30 | "/node_modules" 31 | ], 32 | "moduleFileExtensions": [ 33 | "js", 34 | "json", 35 | "ts" 36 | ], 37 | "transform": { 38 | "^.+\\.(ts|tsx)$": "/node_modules/ts-jest" 39 | }, 40 | "testRegex": "\\.spec\\.(ts|js)x?$", 41 | "setupFiles": [ 42 | "/test/jest-pretest.ts" 43 | ], 44 | "testEnvironment": "node", 45 | "moduleNameMapper": { 46 | "src/index.*": "/src/aurelia-async-binding.ts", 47 | "src/async-binding.*": "/src/async-binding.ts", 48 | "(test\\\\unit\\\\)aurelia-(.*)": "/node_modules/aurelia-$2", 49 | "^.+\\.(css)$": "/test/jest-css-stub.js" 50 | }, 51 | "collectCoverage": true, 52 | "collectCoverageFrom": [ 53 | "src/**/*.{js,ts}", 54 | "!**/*.spec.{js,ts}", 55 | "!**/node_modules/**", 56 | "!**/test/**" 57 | ], 58 | "coverageDirectory": "/test/coverage-jest", 59 | "coveragePathIgnorePatterns": [ 60 | "/node_modules/" 61 | ], 62 | "coverageReporters": [ 63 | "json", 64 | "lcov", 65 | "text", 66 | "html" 67 | ] 68 | }, 69 | "repository": { 70 | "type": "git", 71 | "url": "git+https://github.com/zewa666/aurelia-async-binding.git" 72 | }, 73 | "author": "Vildan Softic ", 74 | "license": "MIT", 75 | "homepage": "https://github.com/zewa666/aurelia-async-binding#readme", 76 | "bugs": { 77 | "url": "https://github.com/zewa666/aurelia-async-binding/issues" 78 | }, 79 | "jspm": { 80 | "registry": "npm", 81 | "jspmPackage": true, 82 | "main": "aurelia-async-binding", 83 | "format": "cjs", 84 | "directories": { 85 | "dist": "dist/commonjs" 86 | } 87 | }, 88 | "dependencies": { 89 | "aurelia-binding": "^2.5.4", 90 | "aurelia-framework": "^1.4.1", 91 | "aurelia-pal": "^1.8.2" 92 | }, 93 | "devDependencies": { 94 | "@types/jest": "^29.0.0", 95 | "@types/node": "^18.7.16", 96 | "aurelia-bootstrapper": "^2.4.0", 97 | "aurelia-loader-nodejs": "^1.1.0", 98 | "aurelia-pal-browser": "^1.8.1", 99 | "aurelia-pal-nodejs": "^2.0.0", 100 | "aurelia-polyfills": "^1.3.4", 101 | "aurelia-testing": "^1.1.0", 102 | "concurrently": "^7.4.0", 103 | "coveralls": "^3.1.1", 104 | "cross-env": "^7.0.3", 105 | "jest": "^29.0.2", 106 | "jest-css-modules": "^2.1.0", 107 | "jsdom": "20.0.0", 108 | "rimraf": "^3.0.2", 109 | "rxjs": "^7.5.6", 110 | "ts-jest": "^29.0.0", 111 | "tslint": "^5.20.1", 112 | "typescript": "^4.8.3" 113 | }, 114 | "peerDependencies": { 115 | "rxjs": "^7.5.0" 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/async-binding.ts: -------------------------------------------------------------------------------- 1 | import { Observable, Subscription } from "rxjs"; 2 | import { bindingBehavior } from "aurelia-framework"; 3 | import { Binding } from "aurelia-binding"; 4 | 5 | export interface AsyncAureliaBinding extends Binding { 6 | originalupdateTarget(value: any): void; 7 | _subscription?: Subscription; 8 | } 9 | 10 | export interface AsyncBindingBehaviorOptions { 11 | catch: any; 12 | completed: () => void; 13 | error: any; 14 | property: string; 15 | } 16 | 17 | @bindingBehavior("async") 18 | export class asyncBindingBehavior { 19 | 20 | getPropByPath(obj: any, keyPath: string) { 21 | return keyPath 22 | .split(".") 23 | .reduce((prev, curr) => prev[curr], obj); 24 | } 25 | 26 | bind(binding: AsyncAureliaBinding, _source: string, options?: AsyncBindingBehaviorOptions) { 27 | binding.originalupdateTarget = binding.updateTarget || (() => {}); 28 | 29 | binding.updateTarget = (a) => { 30 | if (binding._subscription && 31 | typeof binding._subscription.unsubscribe === "function") { 32 | binding._subscription.unsubscribe(); 33 | } 34 | 35 | if (a && typeof a.then === "function") { 36 | a.then((res: any) => binding.originalupdateTarget(options && options.property ? this.getPropByPath(res, options.property) : res)); 37 | 38 | if (options && options.catch) { 39 | a.catch((res: any) => typeof options.catch === "function" 40 | ? options.catch(res) 41 | : binding.originalupdateTarget(options.catch)); 42 | } 43 | } else if (a instanceof Observable) { 44 | const error = options 45 | ? typeof options.error === "function" 46 | ? options.error 47 | : () => { binding.originalupdateTarget(options && options.property ? this.getPropByPath(options.error, options.property) : options.error); } 48 | : undefined; 49 | 50 | binding._subscription = a.subscribe( 51 | (res) => { 52 | binding.originalupdateTarget(options && options.property ? this.getPropByPath(res, options.property) : res); 53 | }, 54 | error, 55 | options ? options.completed : undefined 56 | ); 57 | } 58 | else { 59 | binding.originalupdateTarget(a); 60 | } 61 | }; 62 | } 63 | 64 | unbind(binding: AsyncAureliaBinding) { 65 | binding.updateTarget = binding.originalupdateTarget; 66 | (binding as any).originalupdateTarget = undefined; 67 | 68 | if (binding._subscription && 69 | typeof binding._subscription.unsubscribe === "function") { 70 | binding._subscription.unsubscribe(); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/aurelia-async-binding.ts: -------------------------------------------------------------------------------- 1 | import { FrameworkConfiguration } from "aurelia-framework"; 2 | import { PLATFORM } from "aurelia-pal"; 3 | 4 | export function configure(aurelia: FrameworkConfiguration) { 5 | aurelia.globalResources([ 6 | PLATFORM.moduleName("./async-binding") 7 | ]); 8 | } 9 | 10 | export * from "./async-binding"; 11 | -------------------------------------------------------------------------------- /test/jest-css-stub.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /test/jest-pretest.ts: -------------------------------------------------------------------------------- 1 | import "aurelia-polyfills"; 2 | import { Options } from "aurelia-loader-nodejs"; 3 | import { globalize } from "aurelia-pal-nodejs"; 4 | import * as path from "path"; 5 | 6 | Options.relativeToDir = path.join(__dirname, "unit") 7 | globalize(); 8 | -------------------------------------------------------------------------------- /test/unit/async-binding.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentTester, StageComponent } from "aurelia-testing"; 2 | import { bootstrap } from "aurelia-bootstrapper"; 3 | import { Aurelia } from "aurelia-framework"; 4 | import { of, interval, throwError } from "rxjs"; 5 | import { map, take } from "rxjs/operators"; 6 | 7 | import { asyncBindingBehavior, AsyncAureliaBinding } from "../../src/async-binding"; 8 | 9 | interface SPAFramework { 10 | label: string; 11 | url: string; 12 | } 13 | 14 | const data: SPAFramework[] = [ 15 | { label: "Aurelia", url: "http://aurelia.io" }, 16 | { label: "Angular v4", url: "http://angular.io" }, 17 | { label: "React", url: "https://facebook.github.io/react/" }, 18 | ]; 19 | 20 | function bootstrapPlugin(component: ComponentTester) { 21 | component.bootstrap((aurelia: Aurelia) => { 22 | return aurelia.use.standardConfiguration() 23 | .feature("src"); 24 | }); 25 | } 26 | 27 | describe("the Async Binding Behavior", () => { 28 | it("should render all streamed items out of the box", async () => { 29 | const component = StageComponent 30 | .withResources("mocks/async-binding-vm") 31 | .inView(`
32 | 37 |
` 38 | ) 39 | .boundTo({ frameworks: of(data) }); 40 | 41 | bootstrapPlugin(component); 42 | 43 | await component.create(bootstrap); 44 | 45 | expect(component.element.querySelectorAll("li").length).toBe(data.length); 46 | component.dispose(); 47 | }); 48 | 49 | it("should pluck a single property from the streamed items", async () => { 50 | const delay = 10; 51 | const obs$ = interval(delay).pipe( 52 | map((idx) => data[idx]), 53 | take(data.length) 54 | ); 55 | const component = StageComponent 56 | .withResources("mocks/async-binding-vm") 57 | .inView(`
58 | \${frameworkOverTime & async: { property: 'label' }} 59 |
` 60 | ) 61 | .boundTo({ 62 | frameworkOverTime: obs$ 63 | }); 64 | 65 | bootstrapPlugin(component); 66 | 67 | await component.create(bootstrap); 68 | 69 | await obs$.toPromise(); 70 | expect(component.element.innerHTML.trim()).toBe(data[data.length - 1].label); 71 | component.dispose(); 72 | }); 73 | 74 | it("should allow plucking deep object properties", async () => { 75 | const expectedValue = "bar"; 76 | const component = StageComponent 77 | .withResources("mocks/async-binding-vm") 78 | .inView(`
79 | \${data & async: { property: 'level1.level2.foo' }} 80 |
` 81 | ) 82 | .boundTo({ 83 | data: of({ 84 | level1: { 85 | level2: { 86 | foo: expectedValue 87 | } 88 | } 89 | }) 90 | }); 91 | 92 | bootstrapPlugin(component); 93 | 94 | await component.create(bootstrap); 95 | 96 | expect(component.element.innerHTML.trim()).toBe(expectedValue); 97 | component.dispose(); 98 | }); 99 | 100 | it("should call a provided completedHandler", async () => { 101 | const completed = jest.fn(); 102 | const component = StageComponent 103 | .withResources("mocks/async-binding-vm") 104 | .inView(`
105 | \${frameworks & async: { completed: completed }} 106 |
` 107 | ) 108 | .boundTo({ 109 | frameworks: of(data), 110 | completed 111 | }); 112 | 113 | bootstrapPlugin(component); 114 | 115 | await component.create(bootstrap); 116 | 117 | expect(completed).toHaveBeenCalled(); 118 | component.dispose(); 119 | }); 120 | 121 | it("should call a provided error handler and pass the error", async () => { 122 | const expectedErrorMessage = "Failed on purpose"; 123 | const errorHandler = jest.fn(); 124 | const component = StageComponent 125 | .withResources("mocks/async-binding-vm") 126 | .inView(`
127 | \${frameworks & async: { error: errorHandler }} 128 |
` 129 | ) 130 | .boundTo({ 131 | frameworks: throwError(expectedErrorMessage), 132 | errorHandler 133 | }); 134 | 135 | bootstrapPlugin(component); 136 | 137 | await component.create(bootstrap); 138 | 139 | expect(errorHandler).toHaveBeenCalledWith(expectedErrorMessage); 140 | component.dispose(); 141 | }); 142 | 143 | it("should cleanup previously defined subscriptions", () => { 144 | const sut = new asyncBindingBehavior(); 145 | const binding = {} as AsyncAureliaBinding; 146 | const stream$ = of("test"); 147 | 148 | sut.bind(binding, "", undefined); 149 | binding.updateTarget?.(stream$); 150 | expect(binding._subscription).toBeDefined(); 151 | 152 | const bindingSpy = jest.spyOn(binding._subscription!, "unsubscribe"); 153 | binding.updateTarget?.(stream$); 154 | 155 | expect(bindingSpy).toHaveBeenCalled(); 156 | }); 157 | }); 158 | -------------------------------------------------------------------------------- /test/unit/mocks/async-binding-vm.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /test/unit/mocks/async-binding-vm.ts: -------------------------------------------------------------------------------- 1 | export class AsyncBindingVm { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "moduleResolution": "node", 5 | "target": "es5", 6 | "lib": [ 7 | "es2017", 8 | "dom" 9 | ], 10 | "outDir": "dist/commonjs", 11 | "noImplicitAny": true, 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "noImplicitReturns": true, 15 | "strictNullChecks": true, 16 | "declaration": true, 17 | "forceConsistentCasingInFileNames": true, 18 | "experimentalDecorators": true, 19 | "noEmitHelpers": false, 20 | "strict": true 21 | }, 22 | "exclude": [ 23 | ".vscode", 24 | "dist", 25 | "doc", 26 | "node_modules", 27 | "test" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "quotemark": [true, "double"], 4 | "object-literal-sort-keys": false, 5 | "ordered-imports": [false], 6 | "whitespace": [true, "check-branch", "check-decl", "check-operator", "check-module", "check-separator", "check-type"], 7 | "interface-name": [true, "never-prefix"], 8 | "no-shadowed-variable": false, 9 | "no-string-literal": false 10 | } 11 | } 12 | --------------------------------------------------------------------------------