-
Notifications
You must be signed in to change notification settings - Fork 0
/
macroable.ts
77 lines (72 loc) · 2.3 KB
/
macroable.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import { MacroCallback, MacroOptions, MacroabledProperties, Macroabled, AssignedPropertyKey } from './types';
import isMacroedWith from './is/isMacroedWith';
import _macro from './macro';
import _mixin from './mixin';
/**
* Make an object/function "macroable".
*
* A "macroable"d object or function is an object/function that implements
* the following methods:
* - **hasMacro**: behaves exactly like the `isMacroedWith()` function, and where the "target" is the object/function itself.
* - **macro**: behaves exactly like the `macro()` function, and where the "target" is the object/function itself.
* - **mixin**: behaves exactly like the `mixin()` function, and where the "target" is the object/function itself.
*
* @example
* ```js
* import { macroable } from '@vicgutt/macrojs';
*
* class Week {}
*
* macroable(Week);
*
* Week.prototype.macro('totalDays', 7);
* Week.prototype.mixin({
* days: ['monday', '...'],
* firstDay(country, _default = 'monday') {
* if (country === 'US') {
* return 'sunday';
* }
*
* if (country === 'FR') {
* return 'monday';
* }
*
* return _default;
* },
* });
*
* Week.prototype.hasMacro('totalDays'); // true
* Week.prototype.hasMacro('days'); // true
* Week.prototype.hasMacro('firstDay'); // true
* Week.prototype.hasMacro('nope'); // false
*
* Week.prototype.firstDay('FR'); // 'monday'
* new Week().firstDay('FR'); // 'monday'
* ```
*/
export default function macroable<T>(
target: T,
callback: MacroCallback<T, Omit<MacroabledProperties, '__macros__'>> = null,
options: MacroOptions = {}
): T & Macroabled<T> {
_mixin(
target,
{
hasMacro,
macro,
mixin,
},
callback,
options
);
return target as T & Macroabled<T>;
}
function hasMacro(this: unknown, names: AssignedPropertyKey | AssignedPropertyKey[]): boolean {
return isMacroedWith(this, names);
}
function macro(this: unknown, propertyName: string, propertyValue: unknown, options: MacroOptions = {}): void {
_macro(this, propertyName, propertyValue, options);
}
function mixin<T, P>(this: T, properties: P, callback: MacroCallback<T, P> = null, options: MacroOptions = {}): void {
_mixin(this, properties, callback, options);
}