Skip to content

Commit

Permalink
feat: (experimental feature) applyAspect to join advice together in a…
Browse files Browse the repository at this point in the history
… single declaration
  • Loading branch information
k1r0s committed Dec 13, 2017
1 parent f93ba88 commit 074a022
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 1 deletion.
14 changes: 14 additions & 0 deletions src/apply-aspect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export function applyAspect(advicePool: any) {
return function(target) {
for (let key in advicePool) {
if(key === "constructor") {
advicePool[key].forEach(advice => target = advice(target))
} else {
advicePool[key].forEach(advice => {
Object.defineProperty(target.prototype, key, advice(target, key, Object.getOwnPropertyDescriptor(target.prototype, key)))
})
}
}
return target
}
}
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { afterMethod, beforeMethod, afterInstance, beforeInstance } from "./decorators"
export { AdviceRef, ClassSignature, Metadata, MethodSignature } from "./interfaces"
export { onException } from "./onException"
export { onException } from "./on-exception"
export { applyAspect } from "./apply-aspect"
9 changes: 9 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,12 @@ export interface MethodSignature<B, K> {
export interface ClassSignature<B> {
(target: B)
}

export interface AspectBuilder {
(definition: AspectDefinition)
}

export interface AspectDefinition {
decorateClass: Function,
decorateMethod: Function,
}
File renamed without changes.
73 changes: 73 additions & 0 deletions test/aspect.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { applyAspect, beforeMethod, afterMethod } from "../src"

const methodSpy = jest.fn()

const Delay = secs => meta => setTimeout(meta.commit, secs)

const Cache = (_ => {
const CACHE_KEY = "#CACHE"
return {
read: meta => {
if (!meta.scope[CACHE_KEY]) meta.scope[CACHE_KEY] = {}

if (meta.scope[CACHE_KEY][meta.key]) {
meta.result = meta.scope[CACHE_KEY][meta.key]
meta.prevent()
}
},
write: meta => {
meta.scope[CACHE_KEY][meta.key] = meta.result
}
}
})()

@applyAspect({
"_veryHeavyCalculation": [beforeMethod(Cache.read), afterMethod(Cache.write)],
"doSomething": [beforeMethod(Delay(300))]
})
class Person {
name
age
constructor (name, yearBorn) {
this.name = name
this.age = new Date(yearBorn, 1, 1)
}

_veryHeavyCalculation () {
methodSpy()
const today = new Date()
return today.getFullYear() - this.age.getFullYear()
}

sayHello () {
return `hello, I'm ${this.name}, and I'm ${this._veryHeavyCalculation()} years old`
}

doSomething (cbk) {
cbk()
}
}

let personInstance

describe("advance reflect.advice specs", () => {
beforeAll(() => {
personInstance = new Person("Manuelo", 1998)
})

it("cache advices should avoid '_veryHeavyCalculation' to be called more than once", () => {
personInstance.sayHello()
personInstance.sayHello()
personInstance.sayHello()
expect(methodSpy).toHaveBeenCalledTimes(1)

})

it("Delay advice should stop the execution for at least one segond", done => {
const time = Date.now()
personInstance.doSomething(() => {
expect(Date.now() - time).toBeGreaterThan(280)
done()
})
})
})

0 comments on commit 074a022

Please sign in to comment.