From 3ab2a21cb78e901b7a3ce09525f024643faca601 Mon Sep 17 00:00:00 2001 From: danilradkovsky Date: Thu, 3 Oct 2019 11:55:36 +0300 Subject: [PATCH 1/5] Extract decorators from index.ts to the decorators directory --- core.ts | 96 ++----------------------------------- decorators/event_emitter.ts | 11 +++++ decorators/inject/index.ts | 11 +++++ decorators/input/index.ts | 17 +++++++ decorators/output/index.ts | 54 +++++++++++++++++++++ test/component.test.ts | 4 +- test/inject.test.ts | 2 +- test/input.test.ts | 4 +- test/output.test.ts | 3 +- 9 files changed, 105 insertions(+), 97 deletions(-) create mode 100644 decorators/event_emitter.ts create mode 100644 decorators/inject/index.ts create mode 100644 decorators/input/index.ts create mode 100644 decorators/output/index.ts diff --git a/core.ts b/core.ts index fd2f589..69c8e22 100644 --- a/core.ts +++ b/core.ts @@ -1,96 +1,8 @@ -import {ComponentMetadataService} from "./decorators/component/metadata.service"; -import {IComponentClass} from "./decorators/component/interfaces"; - export * from "./decorators/ng-module"; export * from "./decorators/component"; export * from "./decorators/directive"; +export * from "./decorators/input"; +export * from "./decorators/output"; +export * from "./decorators/inject"; export * from "./decorators/lifecycle_hooks"; - -export function Input(alias?: string): PropertyDecorator { - return function (target: IComponentClass, property: string) { - const componentMetadata = new ComponentMetadataService(target.constructor); - - if (!target.constructor.bindings) { - target.constructor.bindings = {}; - } - - const attrBinding = alias ? alias : property; - - target.constructor.bindings[property] = "<" + attrBinding; - componentMetadata.addInput(property, attrBinding); - }; -} - -export function Output(alias?: string): PropertyDecorator { - return function (target: IComponentClass, property: string) { - const componentMetadata = new ComponentMetadataService(target.constructor); - - if (!target.constructor.bindings) { - target.constructor.bindings = {}; - } - - const privateCallbackName = `__${property}`; - const attrBinding = alias ? alias : property; - - target.constructor.bindings[privateCallbackName] = `&${attrBinding}`; - componentMetadata.addOutput(property, attrBinding); - - Object.defineProperty(target, privateCallbackName, { - set: function (callback: Function) { - if (!this.__callbackCache) { - this.__callbackCache = {}; - } - - if (typeof callback === "function") { - this.__callbackCache[property] = callback; - } - }, - enumerable: false, - configurable: true - }); - - Object.defineProperty(target, property, { - set: function (eventEmitterInstance) { - if (!this.__eventEmitterCache) { - this.__eventEmitterCache = {}; - } - - if (eventEmitterInstance && eventEmitterInstance.subscribe) { - eventEmitterInstance.subscribe((eventData: any) => { - if (typeof this.__callbackCache[property] === "function") { - this.__callbackCache[property]({$event: eventData}); - } - }); - this.__eventEmitterCache[property] = eventEmitterInstance; - } - }, - get: function () { - return this.__eventEmitterCache[property]; - }, - enumerable: true, - configurable: true - }); - }; -} - -export function Inject(dependencyName: string): ParameterDecorator { - return function (target: IComponentClass, property: string, parameterIndex: number) { - if (!target.$inject) { - target.$inject = []; - } - - target.$inject[parameterIndex] = dependencyName; - }; -} - -export class EventEmitter { - private listeners: Array = []; - - emit(event: any = null) { - this.listeners.forEach(callback => callback.call(null, event)); - } - - subscribe(callback: Function) { - this.listeners.push(callback); - } -} +export * from "./decorators/event_emitter"; diff --git a/decorators/event_emitter.ts b/decorators/event_emitter.ts new file mode 100644 index 0000000..655bc62 --- /dev/null +++ b/decorators/event_emitter.ts @@ -0,0 +1,11 @@ +export class EventEmitter { + private listeners: Array = []; + + emit(event: any = null) { + this.listeners.forEach(callback => callback.call(null, event)); + } + + subscribe(callback: Function) { + this.listeners.push(callback); + } +} diff --git a/decorators/inject/index.ts b/decorators/inject/index.ts new file mode 100644 index 0000000..32524c5 --- /dev/null +++ b/decorators/inject/index.ts @@ -0,0 +1,11 @@ +import {IComponentClass} from "../component/interfaces"; + +export function Inject(dependencyName: string): ParameterDecorator { + return function (target: IComponentClass, property: string, parameterIndex: number) { + if (!target.$inject) { + target.$inject = []; + } + + target.$inject[parameterIndex] = dependencyName; + }; +} diff --git a/decorators/input/index.ts b/decorators/input/index.ts new file mode 100644 index 0000000..d5368c0 --- /dev/null +++ b/decorators/input/index.ts @@ -0,0 +1,17 @@ +import {IComponentClass} from "../component/interfaces"; +import {ComponentMetadataService} from "../component/metadata.service"; + +export function Input(alias?: string): PropertyDecorator { + return function (target: IComponentClass, property: string) { + const componentMetadata = new ComponentMetadataService(target.constructor); + + if (!target.constructor.bindings) { + target.constructor.bindings = {}; + } + + const attrBinding = alias ? alias : property; + + target.constructor.bindings[property] = "<" + attrBinding; + componentMetadata.addInput(property, attrBinding); + }; +} diff --git a/decorators/output/index.ts b/decorators/output/index.ts new file mode 100644 index 0000000..b1733d6 --- /dev/null +++ b/decorators/output/index.ts @@ -0,0 +1,54 @@ +import {IComponentClass} from "../component/interfaces"; +import {ComponentMetadataService} from "../component/metadata.service"; + +export function Output(alias?: string): PropertyDecorator { + return function (target: IComponentClass, property: string) { + const componentMetadata = new ComponentMetadataService(target.constructor); + + if (!target.constructor.bindings) { + target.constructor.bindings = {}; + } + + const privateCallbackName = `__${property}`; + const attrBinding = alias ? alias : property; + + target.constructor.bindings[privateCallbackName] = `&${attrBinding}`; + componentMetadata.addOutput(property, attrBinding); + + Object.defineProperty(target, privateCallbackName, { + set: function (callback: Function) { + if (!this.__callbackCache) { + this.__callbackCache = {}; + } + + if (typeof callback === "function") { + this.__callbackCache[property] = callback; + } + }, + enumerable: false, + configurable: true + }); + + Object.defineProperty(target, property, { + set: function (eventEmitterInstance) { + if (!this.__eventEmitterCache) { + this.__eventEmitterCache = {}; + } + + if (eventEmitterInstance && eventEmitterInstance.subscribe) { + eventEmitterInstance.subscribe((eventData: any) => { + if (typeof this.__callbackCache[property] === "function") { + this.__callbackCache[property]({$event: eventData}); + } + }); + this.__eventEmitterCache[property] = eventEmitterInstance; + } + }, + get: function () { + return this.__eventEmitterCache[property]; + }, + enumerable: true, + configurable: true + }); + }; +} diff --git a/test/component.test.ts b/test/component.test.ts index 759c9f6..f3c6387 100644 --- a/test/component.test.ts +++ b/test/component.test.ts @@ -1,5 +1,7 @@ import "reflect-metadata"; -import {Component, Input, Output} from "../core"; +import {Component} from "../core"; +import {Input} from "../decorators/input"; +import {Output} from "../decorators/output"; @Component({ template: `
` diff --git a/test/inject.test.ts b/test/inject.test.ts index dc1d3d8..c12665d 100644 --- a/test/inject.test.ts +++ b/test/inject.test.ts @@ -1,4 +1,4 @@ -import {Inject} from "../core"; +import {Inject} from "../decorators/inject"; class Test { constructor( diff --git a/test/input.test.ts b/test/input.test.ts index 9433235..8aec2b5 100644 --- a/test/input.test.ts +++ b/test/input.test.ts @@ -1,11 +1,11 @@ import "reflect-metadata"; -import {Input} from "../core"; +import {Input} from "../decorators/input"; class Test { @Input("prop2") prop: string; } -describe("Input decorator", function() { +describe("input decorator", function() { let instance: any; beforeEach(function() { diff --git a/test/output.test.ts b/test/output.test.ts index 562f0d7..9e78ee4 100644 --- a/test/output.test.ts +++ b/test/output.test.ts @@ -1,5 +1,6 @@ import "reflect-metadata"; -import {EventEmitter, Output} from "../core"; +import {EventEmitter} from "../decorators/event_emitter"; +import {Output} from "../decorators/output"; class TestWithOneOutput { @Output("onAliasCallback") onCallback: Function; From b69c215649cfd5e05df75401ac5a55a0c1ccb6be Mon Sep 17 00:00:00 2001 From: danilradkovsky Date: Thu, 3 Oct 2019 15:13:28 +0300 Subject: [PATCH 2/5] Add generics for EventEmitter --- decorators/event_emitter.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/decorators/event_emitter.ts b/decorators/event_emitter.ts index 655bc62..11f402f 100644 --- a/decorators/event_emitter.ts +++ b/decorators/event_emitter.ts @@ -1,11 +1,11 @@ -export class EventEmitter { - private listeners: Array = []; +export class EventEmitter { + private listeners: Array<(arg: T) => void> = []; - emit(event: any = null) { + emit(event: T | null = null) { this.listeners.forEach(callback => callback.call(null, event)); } - subscribe(callback: Function) { + subscribe(callback: (arg: T) => void) { this.listeners.push(callback); } } From e977088192a8732908d7a7195788721ad459c516 Mon Sep 17 00:00:00 2001 From: danilradkovsky Date: Thu, 3 Oct 2019 15:29:17 +0300 Subject: [PATCH 3/5] Fix argument naming --- decorators/event_emitter.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/decorators/event_emitter.ts b/decorators/event_emitter.ts index 11f402f..005d9f8 100644 --- a/decorators/event_emitter.ts +++ b/decorators/event_emitter.ts @@ -1,11 +1,11 @@ export class EventEmitter { - private listeners: Array<(arg: T) => void> = []; + private listeners: Array<(event: T) => void> = []; emit(event: T | null = null) { this.listeners.forEach(callback => callback.call(null, event)); } - subscribe(callback: (arg: T) => void) { + subscribe(callback: (event: T) => void) { this.listeners.push(callback); } } From 9e70dbda596b933a7327354cb97872c2b471ff91 Mon Sep 17 00:00:00 2001 From: danilradkovsky Date: Thu, 3 Oct 2019 15:30:19 +0300 Subject: [PATCH 4/5] Fix argument type for emit --- decorators/event_emitter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/decorators/event_emitter.ts b/decorators/event_emitter.ts index 005d9f8..9f33b2a 100644 --- a/decorators/event_emitter.ts +++ b/decorators/event_emitter.ts @@ -1,7 +1,7 @@ export class EventEmitter { private listeners: Array<(event: T) => void> = []; - emit(event: T | null = null) { + emit(event?: T) { this.listeners.forEach(callback => callback.call(null, event)); } From 55ec6c71996ef8db4ff04660661095cc2217cb98 Mon Sep 17 00:00:00 2001 From: danilradkovsky Date: Thu, 3 Oct 2019 15:34:23 +0300 Subject: [PATCH 5/5] Change imports in tests --- test/component.test.ts | 4 +--- test/inject.test.ts | 13 ++++++++----- test/input.test.ts | 2 +- test/output.test.ts | 7 +++---- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/test/component.test.ts b/test/component.test.ts index f3c6387..759c9f6 100644 --- a/test/component.test.ts +++ b/test/component.test.ts @@ -1,7 +1,5 @@ import "reflect-metadata"; -import {Component} from "../core"; -import {Input} from "../decorators/input"; -import {Output} from "../decorators/output"; +import {Component, Input, Output} from "../core"; @Component({ template: `
` diff --git a/test/inject.test.ts b/test/inject.test.ts index c12665d..7e10662 100644 --- a/test/inject.test.ts +++ b/test/inject.test.ts @@ -1,17 +1,20 @@ -import {Inject} from "../decorators/inject"; +import {Inject} from "../core"; class Test { constructor( @Inject("service") service: Function, @Inject("service2") service2: Function - ) {} + ) { + } } -describe("Inject decorator", function() { +describe("Inject decorator", function () { let instance: any; - beforeEach(function() { - instance = new Test(() => {}, () => {}); + beforeEach(function () { + instance = new Test(() => { + }, () => { + }); }); test("should create $inject", function () { diff --git a/test/input.test.ts b/test/input.test.ts index 8aec2b5..7bc515b 100644 --- a/test/input.test.ts +++ b/test/input.test.ts @@ -1,5 +1,5 @@ import "reflect-metadata"; -import {Input} from "../decorators/input"; +import {Input} from "../core"; class Test { @Input("prop2") prop: string; diff --git a/test/output.test.ts b/test/output.test.ts index 9e78ee4..f57fa02 100644 --- a/test/output.test.ts +++ b/test/output.test.ts @@ -1,6 +1,5 @@ import "reflect-metadata"; -import {EventEmitter} from "../decorators/event_emitter"; -import {Output} from "../decorators/output"; +import {EventEmitter, Output} from "../core"; class TestWithOneOutput { @Output("onAliasCallback") onCallback: Function; @@ -11,11 +10,11 @@ class TestWithManyOutputs { @Output("cb2") callback2: Function; } -describe("Output decorator", function() { +describe("Output decorator", function () { let testOneOutput: any, testManyOutputs: any; - beforeEach(function() { + beforeEach(function () { testOneOutput = new TestWithOneOutput(); testManyOutputs = new TestWithManyOutputs(); });