Skip to content

Commit

Permalink
refactor: raise exception when macros and getters are not initiated o…
Browse files Browse the repository at this point in the history
…n class

BREAKING CHANGE: Removed _ prefix from getters and macros static properties
  • Loading branch information
thetutlage committed Dec 19, 2019
1 parent a4c40b8 commit 66c046e
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 19 deletions.
28 changes: 18 additions & 10 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,16 @@ export interface MacroableConstructorContract<T extends any> {
* 2. Can define singleton getters.
*/
export abstract class Macroable {
protected static _macros: MacroableMap = {}
protected static _getters: MacroableMap = {}
protected static macros: MacroableMap = {}
protected static getters: MacroableMap = {}

constructor () {
if (!this.constructor.hasOwnProperty('macros') || !this.constructor.hasOwnProperty('getters')) {
throw new Error(
'Set static properties "macros = {}" and "getters = {}" on the class for the macroable to work.',
)
}
}

/**
* Add a macro to the class. This method is a better to manually adding
Expand All @@ -43,15 +51,15 @@ export abstract class Macroable {
* ```
*/
public static macro<T extends any = any> (name: string, callback: MacroableFn<T>) {
this._macros[name] = callback
this.macros[name] = callback
this.prototype[name] = callback
}

/**
* Return the existing macro or null if it doesn't exists
*/
public static getMacro (name: string): MacroableFn<any> | undefined {
return this._macros[name]
return this.macros[name]
}

/**
Expand Down Expand Up @@ -92,7 +100,7 @@ export abstract class Macroable {
return this[propName]
} : callback

this._getters[name] = wrappedCallback
this.getters[name] = wrappedCallback

Object.defineProperty(this.prototype, name, {
get: wrappedCallback,
Expand All @@ -105,7 +113,7 @@ export abstract class Macroable {
* Return the existing getter or null if it doesn't exists
*/
public static getGetter (name: string): MacroableFn<any> | undefined {
return this._getters[name]
return this.getters[name]
}

/**
Expand All @@ -119,9 +127,9 @@ export abstract class Macroable {
* Cleanup getters and macros from the class
*/
public static hydrate () {
Object.keys(this._macros).forEach((key) => Reflect.deleteProperty(this.prototype, key))
Object.keys(this._getters).forEach((key) => Reflect.deleteProperty(this.prototype, key))
this._macros = {}
this._getters = {}
Object.keys(this.macros).forEach((key) => Reflect.deleteProperty(this.prototype, key))
Object.keys(this.getters).forEach((key) => Reflect.deleteProperty(this.prototype, key))
this.macros = {}
this.getters = {}
}
}
27 changes: 18 additions & 9 deletions test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import test from 'japa'
import { Macroable } from './index'

class Parent extends Macroable {}
Parent['_macros'] = {}
Parent['_getter'] = {}
Parent['macros'] = {}
Parent['getters'] = {}

test.group('Macroable', (group) => {
group.beforeEach(() => {
group.afterEach(() => {
Parent.hydrate()
})

Expand Down Expand Up @@ -70,20 +70,20 @@ test.group('Macroable', (group) => {

Parent.hydrate()

assert.deepEqual(Parent['_macros'], {})
assert.deepEqual(Parent['_getters'], {})
assert.deepEqual(Parent['macros'], {})
assert.deepEqual(Parent['getters'], {})
assert.equal(new Parent()['foo'], undefined)
assert.equal(new Parent()['bar'], undefined)
})

test('static methods should not be shared', (assert) => {
class Foo extends Macroable {}
Foo['_macros'] = {}
Foo['_getters'] = {}
Foo['macros'] = {}
Foo['getters'] = {}

class Bar extends Macroable {}
Bar['_macros'] = {}
Bar['_getters'] = {}
Bar['macros'] = {}
Bar['getters'] = {}

Foo.macro('foo', function foo () {})
assert.isFunction(Foo.getMacro('foo'))
Expand Down Expand Up @@ -124,4 +124,13 @@ test.group('Macroable', (group) => {
assert.equal(m1['foo'], 'bar')
assert.equal(getterCalledCounts, 2)
})

test('raise exception when macros and getters are not initiated as objects', (assert) => {
class Foo extends Macroable {}
const fn = () => new Foo()
assert.throw(
fn,
'Set static properties "macros = {}" and "getters = {}" on the class for the macroable to work.',
)
})
})

0 comments on commit 66c046e

Please sign in to comment.