@praxisjs/decorators 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/dist/__tests__/properties.test.js +245 -15
- package/dist/__tests__/properties.test.js.map +1 -1
- package/dist/create-accessor-decorator.d.ts +14 -0
- package/dist/create-accessor-decorator.d.ts.map +1 -0
- package/dist/create-accessor-decorator.js +27 -0
- package/dist/create-accessor-decorator.js.map +1 -0
- package/dist/create-getter-decorator.d.ts +14 -0
- package/dist/create-getter-decorator.d.ts.map +1 -1
- package/dist/create-getter-decorator.js +17 -0
- package/dist/create-getter-decorator.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/properties/computed.d.ts +11 -1
- package/dist/properties/computed.d.ts.map +1 -1
- package/dist/properties/computed.js +23 -11
- package/dist/properties/computed.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/properties.test.ts +301 -15
- package/src/create-accessor-decorator.ts +45 -0
- package/src/create-getter-decorator.ts +39 -0
- package/src/index.ts +8 -0
- package/src/properties/computed.ts +48 -11
|
@@ -5,6 +5,23 @@ export function createGetterDecorator(behavior) {
|
|
|
5
5
|
};
|
|
6
6
|
};
|
|
7
7
|
}
|
|
8
|
+
export function createWritableGetterDecorator(behavior) {
|
|
9
|
+
return function (target, context) {
|
|
10
|
+
context.addInitializer(function () {
|
|
11
|
+
const instance = this;
|
|
12
|
+
const binding = behavior.bind(instance, context.name, target);
|
|
13
|
+
const descriptor = {
|
|
14
|
+
get: binding.get,
|
|
15
|
+
configurable: true,
|
|
16
|
+
enumerable: false,
|
|
17
|
+
};
|
|
18
|
+
if (binding.set !== undefined)
|
|
19
|
+
descriptor.set = binding.set;
|
|
20
|
+
Object.defineProperty(instance, context.name, descriptor);
|
|
21
|
+
});
|
|
22
|
+
return target;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
8
25
|
export function createGetterObserverDecorator(behavior) {
|
|
9
26
|
return function (target, context) {
|
|
10
27
|
context.addInitializer(function () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-getter-decorator.js","sourceRoot":"","sources":["../src/create-getter-decorator.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,qBAAqB,CAAC,QAAwB;IAC5D,OAAO,UACL,MAAyB,EACzB,QAA8C;QAE9C,OAAO;YACL,OAAO,QAAQ,CAAC,IAAI,CAClB,MAAmC,EACnC,IAAc,CACf,EAAO,CAAC;QACX,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAeD,MAAM,UAAU,6BAA6B,CAAC,QAAgC;IAC5E,OAAO,UACL,MAAyB,EACzB,OAA6C;QAE7C,OAAO,CAAC,cAAc,CAAC;YACrB,QAAQ,CAAC,OAAO,CACd,MAAmC,EACnC,IAAc,EACd,OAAO,CAAC,IAAc,CACvB,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"create-getter-decorator.js","sourceRoot":"","sources":["../src/create-getter-decorator.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,qBAAqB,CAAC,QAAwB;IAC5D,OAAO,UACL,MAAyB,EACzB,QAA8C;QAE9C,OAAO;YACL,OAAO,QAAQ,CAAC,IAAI,CAClB,MAAmC,EACnC,IAAc,CACf,EAAO,CAAC;QACX,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAqBD,MAAM,UAAU,6BAA6B,CAAC,QAAgC;IAC5E,OAAO,UACL,MAAyB,EACzB,OAA6C;QAE7C,OAAO,CAAC,cAAc,CAAC;YACrB,MAAM,QAAQ,GAAG,IAAc,CAAC;YAChC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,MAAmC,CAAC,CAAC;YAC3F,MAAM,UAAU,GAAuB;gBACrC,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,YAAY,EAAE,IAAI;gBAClB,UAAU,EAAE,KAAK;aAClB,CAAC;YACF,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS;gBAAE,UAAU,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;YAC5D,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC;AAeD,MAAM,UAAU,6BAA6B,CAAC,QAAgC;IAC5E,OAAO,UACL,MAAyB,EACzB,OAA6C;QAE7C,OAAO,CAAC,cAAc,CAAC;YACrB,QAAQ,CAAC,OAAO,CACd,MAAmC,EACnC,IAAc,EACd,OAAO,CAAC,IAAc,CACvB,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,5 +7,6 @@ export { type ReactiveHost } from "./reactive-host";
|
|
|
7
7
|
export { createClassDecorator, ClassBehavior, type ClassEnhancement, } from "./create-class-decorator";
|
|
8
8
|
export { createMethodDecorator, type MethodBehavior, } from "./create-method-decorator";
|
|
9
9
|
export { createLifecycleMethodDecorator, type LifecycleMethodBehavior, } from "./create-lifecycle-method-decorator";
|
|
10
|
-
export { createGetterDecorator, type GetterBehavior, createGetterObserverDecorator, type GetterObserverBehavior, } from "./create-getter-decorator";
|
|
10
|
+
export { createGetterDecorator, type GetterBehavior, createWritableGetterDecorator, type WritableGetterBehavior, type WritableGetterBinding, createGetterObserverDecorator, type GetterObserverBehavior, } from "./create-getter-decorator";
|
|
11
|
+
export { createAccessorDecorator, type AccessorBehavior, type AccessorBinding, } from "./create-accessor-decorator";
|
|
11
12
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,QAAQ,EACb,KAAK,SAAS,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,SAAS,EACT,OAAO,EACP,KAAK,SAAS,EACd,OAAO,EACP,MAAM,EACN,QAAQ,EACR,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,MAAM,EACN,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,EACL,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,KAAK,gBAAgB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,qBAAqB,EACrB,KAAK,cAAc,GACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,8BAA8B,EAC9B,KAAK,uBAAuB,GAC7B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,qBAAqB,EACrB,KAAK,cAAc,EACnB,6BAA6B,EAC7B,KAAK,sBAAsB,GAC5B,MAAM,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,QAAQ,EACb,KAAK,SAAS,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,SAAS,EACT,OAAO,EACP,KAAK,SAAS,EACd,OAAO,EACP,MAAM,EACN,QAAQ,EACR,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,MAAM,EACN,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,EACL,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,YAAY,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,KAAK,gBAAgB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,qBAAqB,EACrB,KAAK,cAAc,GACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,8BAA8B,EAC9B,KAAK,uBAAuB,GAC7B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,qBAAqB,EACrB,KAAK,cAAc,EACnB,6BAA6B,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,6BAA6B,EAC7B,KAAK,sBAAsB,GAC5B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,6BAA6B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,5 +6,6 @@ export { createFieldDecorator, } from "./create-field-decorator";
|
|
|
6
6
|
export { createClassDecorator, ClassBehavior, } from "./create-class-decorator";
|
|
7
7
|
export { createMethodDecorator, } from "./create-method-decorator";
|
|
8
8
|
export { createLifecycleMethodDecorator, } from "./create-lifecycle-method-decorator";
|
|
9
|
-
export { createGetterDecorator, createGetterObserverDecorator, } from "./create-getter-decorator";
|
|
9
|
+
export { createGetterDecorator, createWritableGetterDecorator, createGetterObserverDecorator, } from "./create-getter-decorator";
|
|
10
|
+
export { createAccessorDecorator, } from "./create-accessor-decorator";
|
|
10
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,KAAK,GAGN,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,SAAS,EACT,OAAO,EAEP,OAAO,EACP,MAAM,EACN,QAAQ,EACR,kBAAkB,EAGlB,MAAM,EACN,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAgB,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,EACL,oBAAoB,GAGrB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,oBAAoB,EACpB,aAAa,GAEd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,8BAA8B,GAE/B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,qBAAqB,EAErB,6BAA6B,GAE9B,MAAM,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,KAAK,GAGN,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,SAAS,EACT,OAAO,EAEP,OAAO,EACP,MAAM,EACN,QAAQ,EACR,kBAAkB,EAGlB,MAAM,EACN,SAAS,GACV,MAAM,cAAc,CAAC;AACtB,OAAO,EAAgB,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,EACL,oBAAoB,GAGrB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,oBAAoB,EACpB,aAAa,GAEd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,8BAA8B,GAE/B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,qBAAqB,EAErB,6BAA6B,EAG7B,6BAA6B,GAE9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,GAGxB,MAAM,6BAA6B,CAAC"}
|
|
@@ -1,2 +1,12 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface ComputedOptions<T = unknown> {
|
|
2
|
+
get?: (this: object) => T;
|
|
3
|
+
set?: (this: object, value: T) => void;
|
|
4
|
+
}
|
|
5
|
+
export declare function Computed<T, Owner extends object = object>(options: {
|
|
6
|
+
get: (this: Owner) => T;
|
|
7
|
+
set: (this: Owner, value: T) => void;
|
|
8
|
+
}): <This extends object>(target: ClassAccessorDecoratorTarget<This, T>, context: ClassAccessorDecoratorContext<This, T>) => ClassAccessorDecoratorResult<This, T>;
|
|
9
|
+
export declare function Computed(options?: {
|
|
10
|
+
set?: (this: object, value: unknown) => void;
|
|
11
|
+
}): <This, R>(target: (this: This) => R, context: ClassGetterDecoratorContext<This, R>) => (this: This) => R;
|
|
2
12
|
//# sourceMappingURL=computed.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../../src/properties/computed.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"computed.d.ts","sourceRoot":"","sources":["../../src/properties/computed.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,CAAC,CAAC;IAC1B,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;CACxC;AAKD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,KAAK,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE;IAClE,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,CAAC,CAAC;IACxB,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;CACtC,GAAG,CAAC,IAAI,SAAS,MAAM,EACtB,MAAM,EAAE,4BAA4B,CAAC,IAAI,EAAE,CAAC,CAAC,EAC7C,OAAO,EAAE,6BAA6B,CAAC,IAAI,EAAE,CAAC,CAAC,KAC5C,4BAA4B,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAG3C,wBAAgB,QAAQ,CAAC,OAAO,CAAC,EAAE;IACjC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C,GAAG,CAAC,IAAI,EAAE,CAAC,EACV,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,EACzB,OAAO,EAAE,2BAA2B,CAAC,IAAI,EAAE,CAAC,CAAC,KAC1C,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,CAAC"}
|
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import { computed } from "@praxisjs/core/internal";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
import { createAccessorDecorator } from "../create-accessor-decorator";
|
|
3
|
+
import { createWritableGetterDecorator } from "../create-getter-decorator";
|
|
4
|
+
export function Computed(options) {
|
|
5
|
+
const optionsGet = options?.get;
|
|
6
|
+
const optionsSet = options?.set;
|
|
7
|
+
if (optionsGet) {
|
|
8
|
+
return createAccessorDecorator({
|
|
9
|
+
bind(instance, _name, _initialValue) {
|
|
10
|
+
const c = computed(() => optionsGet.call(instance));
|
|
11
|
+
return {
|
|
12
|
+
get: c,
|
|
13
|
+
set: optionsSet ? (value) => { optionsSet.call(instance, value); } : undefined,
|
|
14
|
+
};
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return createWritableGetterDecorator({
|
|
19
|
+
bind(instance, _name, original) {
|
|
20
|
+
const c = computed(() => original.call(instance));
|
|
21
|
+
return {
|
|
22
|
+
get: c,
|
|
23
|
+
set: optionsSet ? (value) => { optionsSet.call(instance, value); } : undefined,
|
|
24
|
+
};
|
|
13
25
|
},
|
|
14
26
|
});
|
|
15
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"computed.js","sourceRoot":"","sources":["../../src/properties/computed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"computed.js","sourceRoot":"","sources":["../../src/properties/computed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAEnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AA0B3E,MAAM,UAAU,QAAQ,CAAc,OAA4B;IAChE,MAAM,UAAU,GAAG,OAAO,EAAE,GAA8C,CAAC;IAC3E,MAAM,UAAU,GAAG,OAAO,EAAE,GAA2D,CAAC;IAExF,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,uBAAuB,CAAC;YAC7B,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,aAAa;gBACjC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACpD,OAAO;oBACL,GAAG,EAAE,CAAC;oBACN,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;iBAC/E,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAED,OAAO,6BAA6B,CAAC;QACnC,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ;YAC5B,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAClD,OAAO;gBACL,GAAG,EAAE,CAAC;gBACN,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;aAC/E,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisjs/decorators",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"typescript": "^5.9.3"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@praxisjs/core": "1.
|
|
19
|
-
"@praxisjs/shared": "0.
|
|
18
|
+
"@praxisjs/core": "1.8.0",
|
|
19
|
+
"@praxisjs/shared": "0.3.0"
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"build": "tsc",
|
|
@@ -4,6 +4,8 @@ import { StatefulComponent } from "@praxisjs/core";
|
|
|
4
4
|
import { signal, computed } from "@praxisjs/core/internal";
|
|
5
5
|
|
|
6
6
|
import { createFieldDecorator } from "../create-field-decorator";
|
|
7
|
+
import { createGetterDecorator } from "../create-getter-decorator";
|
|
8
|
+
import { createAccessorDecorator } from "../create-accessor-decorator";
|
|
7
9
|
import { Watch } from "../functions/watch";
|
|
8
10
|
import { When } from "../functions/when";
|
|
9
11
|
import { Compose } from "../properties/compose";
|
|
@@ -152,39 +154,243 @@ describe("Prop decorator", () => {
|
|
|
152
154
|
|
|
153
155
|
describe("Computed decorator", () => {
|
|
154
156
|
it("wraps a getter in a computed — result is memoized", () => {
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
});
|
|
157
|
+
const s = signal(5);
|
|
158
|
+
const fn = vi.fn(function (this: object) { return s() * 2; });
|
|
158
159
|
|
|
159
|
-
const
|
|
160
|
-
|
|
160
|
+
const { ctx, run } = getterCtx("doubled");
|
|
161
|
+
Computed()(fn, ctx);
|
|
162
|
+
const instance = {} as unknown as StatefulComponent;
|
|
163
|
+
run(instance);
|
|
161
164
|
|
|
162
|
-
const result1 =
|
|
163
|
-
const result2 =
|
|
165
|
+
const result1 = (instance as unknown as Record<string, unknown>).doubled;
|
|
166
|
+
const result2 = (instance as unknown as Record<string, unknown>).doubled;
|
|
164
167
|
expect(result1).toBe(10);
|
|
165
168
|
expect(result2).toBe(10);
|
|
166
|
-
expect(fn).toHaveBeenCalledTimes(1);
|
|
169
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
167
170
|
});
|
|
168
171
|
|
|
169
172
|
it("recomputes when underlying signal changes", () => {
|
|
170
173
|
const s = signal(3);
|
|
171
174
|
const getter = function (this: object) { return s() * 2; };
|
|
172
|
-
const
|
|
175
|
+
const { ctx, run } = getterCtx("val");
|
|
176
|
+
Computed()(getter, ctx);
|
|
173
177
|
const obj = {} as unknown as StatefulComponent;
|
|
174
|
-
|
|
178
|
+
run(obj);
|
|
179
|
+
|
|
180
|
+
expect((obj as unknown as Record<string, unknown>).val).toBe(6);
|
|
175
181
|
s.set(5);
|
|
176
|
-
expect(
|
|
182
|
+
expect((obj as unknown as Record<string, unknown>).val).toBe(10);
|
|
177
183
|
});
|
|
178
184
|
|
|
179
185
|
it("is per-instance — separate computed per object", () => {
|
|
180
186
|
const s = signal(1);
|
|
181
187
|
const getter = function (this: object) { return s(); };
|
|
182
|
-
const
|
|
188
|
+
const { ctx, run } = getterCtx("val");
|
|
189
|
+
Computed()(getter, ctx);
|
|
183
190
|
const a = {} as unknown as StatefulComponent;
|
|
184
191
|
const b = {} as unknown as StatefulComponent;
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
192
|
+
run(a);
|
|
193
|
+
run(b);
|
|
194
|
+
|
|
195
|
+
expect((a as unknown as Record<string, unknown>).val).toBe(1);
|
|
196
|
+
expect((b as unknown as Record<string, unknown>).val).toBe(1);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// ── Computed (writable) ───────────────────────────────────────────────────────
|
|
201
|
+
|
|
202
|
+
function getterCtx(name: string) {
|
|
203
|
+
const initializers: Array<(this: unknown) => void> = [];
|
|
204
|
+
return {
|
|
205
|
+
ctx: {
|
|
206
|
+
name,
|
|
207
|
+
kind: "getter" as const,
|
|
208
|
+
addInitializer(fn: (this: unknown) => void) {
|
|
209
|
+
initializers.push(fn);
|
|
210
|
+
},
|
|
211
|
+
} as unknown as ClassGetterDecoratorContext,
|
|
212
|
+
run(instance: unknown) {
|
|
213
|
+
initializers.forEach((fn) => { fn.call(instance); });
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
describe("Computed decorator — writable (set option)", () => {
|
|
219
|
+
it("setter is called when property is assigned", () => {
|
|
220
|
+
const written: number[] = [];
|
|
221
|
+
const { ctx, run } = getterCtx("double");
|
|
222
|
+
|
|
223
|
+
const s = signal(3);
|
|
224
|
+
const getter = function (this: object) { return s() * 2; };
|
|
225
|
+
Computed({ set: (v: unknown) => { written.push(v as number); } })(getter, ctx);
|
|
226
|
+
|
|
227
|
+
const instance = {} as unknown as StatefulComponent;
|
|
228
|
+
run(instance);
|
|
229
|
+
|
|
230
|
+
(instance as unknown as Record<string, unknown>).double = 42;
|
|
231
|
+
expect(written).toEqual([42]);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("setter receives the component instance as this", () => {
|
|
235
|
+
let capturedThis: unknown;
|
|
236
|
+
const { ctx, run } = getterCtx("val");
|
|
237
|
+
|
|
238
|
+
const getter = function (this: object) { return 0; };
|
|
239
|
+
Computed({ set(this: unknown, _v: unknown) { capturedThis = this; } })(getter, ctx);
|
|
240
|
+
|
|
241
|
+
const instance = { id: "target" } as unknown as StatefulComponent;
|
|
242
|
+
run(instance);
|
|
243
|
+
|
|
244
|
+
(instance as unknown as Record<string, unknown>).val = 99;
|
|
245
|
+
expect(capturedThis).toBe(instance);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("getter still returns the computed value after set option is added", () => {
|
|
249
|
+
const s = signal(5);
|
|
250
|
+
const { ctx, run } = getterCtx("doubled");
|
|
251
|
+
|
|
252
|
+
const getter = function (this: object) { return s() * 2; };
|
|
253
|
+
Computed({ set: (_v: unknown) => { /* no-op */ } })(getter, ctx);
|
|
254
|
+
|
|
255
|
+
const instance = {} as unknown as StatefulComponent;
|
|
256
|
+
run(instance);
|
|
257
|
+
|
|
258
|
+
expect((instance as unknown as Record<string, unknown>).doubled).toBe(10);
|
|
259
|
+
s.set(7);
|
|
260
|
+
expect((instance as unknown as Record<string, unknown>).doubled).toBe(14);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it("setter writes through to underlying signals, updating the getter", () => {
|
|
264
|
+
const s = signal(0);
|
|
265
|
+
const { ctx, run } = getterCtx("celsius");
|
|
266
|
+
|
|
267
|
+
const getter = function (this: object) { return s(); };
|
|
268
|
+
Computed({ set: (v: unknown) => { s.set(v as number); } })(getter, ctx);
|
|
269
|
+
|
|
270
|
+
const instance = {} as unknown as StatefulComponent;
|
|
271
|
+
run(instance);
|
|
272
|
+
|
|
273
|
+
(instance as unknown as Record<string, unknown>).celsius = 100;
|
|
274
|
+
expect((instance as unknown as Record<string, unknown>).celsius).toBe(100);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// ── Computed (accessor form) ──────────────────────────────────────────────────
|
|
279
|
+
|
|
280
|
+
describe("Computed decorator — accessor form ({ get, set })", () => {
|
|
281
|
+
function applyAccessorDecorator<T>(
|
|
282
|
+
options: { get: (this: object) => T; set: (this: object, value: T) => void },
|
|
283
|
+
instance: object,
|
|
284
|
+
): { get: () => T; set: (v: T) => void } {
|
|
285
|
+
const target = {
|
|
286
|
+
get(this: object) { return undefined as T; },
|
|
287
|
+
set(_v: T) { /* original */ },
|
|
288
|
+
};
|
|
289
|
+
const ctx = { kind: "accessor", name: "value" } as unknown as ClassAccessorDecoratorContext<object, T>;
|
|
290
|
+
const result = Computed(options)(target, ctx);
|
|
291
|
+
result.init!.call(instance, undefined as unknown as T);
|
|
292
|
+
return {
|
|
293
|
+
get: () => result.get!.call(instance),
|
|
294
|
+
set: (v: T) => result.set!.call(instance, v),
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
it("get function is wrapped in a computed — result is memoized", () => {
|
|
299
|
+
const s = signal(3);
|
|
300
|
+
const getFn = vi.fn(function (this: object) { return s() * 2; });
|
|
301
|
+
const instance = {};
|
|
302
|
+
const { get } = applyAccessorDecorator({ get: getFn, set: () => { /* no-op */ } }, instance);
|
|
303
|
+
|
|
304
|
+
expect(get()).toBe(6);
|
|
305
|
+
expect(get()).toBe(6);
|
|
306
|
+
expect(getFn).toHaveBeenCalledTimes(1);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it("recomputes when underlying signal changes", () => {
|
|
310
|
+
const s = signal(10);
|
|
311
|
+
const instance = {};
|
|
312
|
+
const { get } = applyAccessorDecorator({
|
|
313
|
+
get(this: object) { return s() + 1; },
|
|
314
|
+
set() { /* no-op */ },
|
|
315
|
+
}, instance);
|
|
316
|
+
|
|
317
|
+
expect(get()).toBe(11);
|
|
318
|
+
s.set(20);
|
|
319
|
+
expect(get()).toBe(21);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
it("set function is called when the setter is invoked", () => {
|
|
323
|
+
const written: number[] = [];
|
|
324
|
+
const instance = {};
|
|
325
|
+
const { set } = applyAccessorDecorator({
|
|
326
|
+
get(this: object) { return 0; },
|
|
327
|
+
set(_v: number) { written.push(_v); },
|
|
328
|
+
}, instance);
|
|
329
|
+
|
|
330
|
+
set(42);
|
|
331
|
+
expect(written).toEqual([42]);
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it("set function receives the component instance as this", () => {
|
|
335
|
+
let capturedThis: unknown;
|
|
336
|
+
const instance = { id: "target" };
|
|
337
|
+
const { set } = applyAccessorDecorator({
|
|
338
|
+
get(this: object) { return 0; },
|
|
339
|
+
set(this: unknown) { capturedThis = this; },
|
|
340
|
+
}, instance);
|
|
341
|
+
|
|
342
|
+
set(1);
|
|
343
|
+
expect(capturedThis).toBe(instance);
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it("set writes through to underlying signals, updating the getter", () => {
|
|
347
|
+
const s = signal(0);
|
|
348
|
+
const instance = {};
|
|
349
|
+
const { get, set } = applyAccessorDecorator({
|
|
350
|
+
get(this: object) { return s(); },
|
|
351
|
+
set(this: object, v: number) { s.set(v); },
|
|
352
|
+
}, instance);
|
|
353
|
+
|
|
354
|
+
set(100);
|
|
355
|
+
expect(get()).toBe(100);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it("is per-instance — separate computed per object", () => {
|
|
359
|
+
const s = signal(5);
|
|
360
|
+
const options = {
|
|
361
|
+
get(this: object) { return s() * 2; },
|
|
362
|
+
set() { /* no-op */ },
|
|
363
|
+
};
|
|
364
|
+
const a = {};
|
|
365
|
+
const b = {};
|
|
366
|
+
const decA = applyAccessorDecorator(options, a);
|
|
367
|
+
const decB = applyAccessorDecorator(options, b);
|
|
368
|
+
|
|
369
|
+
expect(decA.get()).toBe(10);
|
|
370
|
+
expect(decB.get()).toBe(10);
|
|
371
|
+
s.set(7);
|
|
372
|
+
expect(decA.get()).toBe(14);
|
|
373
|
+
expect(decB.get()).toBe(14);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it("accessor form without set — setter is a no-op", () => {
|
|
377
|
+
const s = signal(5);
|
|
378
|
+
const instance = {};
|
|
379
|
+
const target = { get() { return undefined as unknown as number; }, set() { /* original */ } };
|
|
380
|
+
const ctx = { kind: "accessor", name: "value" } as unknown as ClassAccessorDecoratorContext<object, number>;
|
|
381
|
+
// Bypass overload constraint — optionsSet is undefined at runtime
|
|
382
|
+
type AccessorDecoFactory = (opts: { get: (this: object) => number }) => (
|
|
383
|
+
t: typeof target,
|
|
384
|
+
c: typeof ctx,
|
|
385
|
+
) => ClassAccessorDecoratorResult<object, number>;
|
|
386
|
+
const result = (Computed as unknown as AccessorDecoFactory)(
|
|
387
|
+
{ get(this: object) { return s() * 2; } },
|
|
388
|
+
)(target, ctx);
|
|
389
|
+
result.init!.call(instance, 0);
|
|
390
|
+
|
|
391
|
+
expect(result.get!.call(instance)).toBe(10);
|
|
392
|
+
expect(() => { result.set!.call(instance, 99); }).not.toThrow();
|
|
393
|
+
expect(result.get!.call(instance)).toBe(10); // unchanged — no setter
|
|
188
394
|
});
|
|
189
395
|
});
|
|
190
396
|
|
|
@@ -1157,3 +1363,83 @@ describe("createFieldDecorator — additional property", () => {
|
|
|
1157
1363
|
expect((instance as unknown as Record<string, unknown>).extraProp).toBe("extra");
|
|
1158
1364
|
});
|
|
1159
1365
|
});
|
|
1366
|
+
|
|
1367
|
+
// ── createGetterDecorator ─────────────────────────────────────────────────────
|
|
1368
|
+
|
|
1369
|
+
describe("createGetterDecorator", () => {
|
|
1370
|
+
it("calls behavior.wrap on access and returns the wrapped value", () => {
|
|
1371
|
+
const wrap = vi.fn((original: (this: object) => unknown, instance: object) => {
|
|
1372
|
+
return () => (original.call(instance) as number) * 2;
|
|
1373
|
+
});
|
|
1374
|
+
const decorator = createGetterDecorator({ wrap });
|
|
1375
|
+
const originalGetter = function (this: object) { return 5 as unknown; };
|
|
1376
|
+
const ctx = { kind: "getter" } as ClassGetterDecoratorContext<object, number>;
|
|
1377
|
+
const wrapped = decorator(originalGetter as (this: object) => number, ctx);
|
|
1378
|
+
|
|
1379
|
+
const instance = {};
|
|
1380
|
+
expect(wrapped.call(instance)).toBe(10);
|
|
1381
|
+
expect(wrap).toHaveBeenCalledWith(originalGetter, instance);
|
|
1382
|
+
});
|
|
1383
|
+
|
|
1384
|
+
it("passes the correct instance as this to behavior.wrap", () => {
|
|
1385
|
+
let capturedInstance: unknown;
|
|
1386
|
+
const decorator = createGetterDecorator({
|
|
1387
|
+
wrap(_original, instance) {
|
|
1388
|
+
capturedInstance = instance;
|
|
1389
|
+
return () => 0;
|
|
1390
|
+
},
|
|
1391
|
+
});
|
|
1392
|
+
const getter = function (this: object) { return 0 as unknown; };
|
|
1393
|
+
const ctx = { kind: "getter" } as ClassGetterDecoratorContext<object, number>;
|
|
1394
|
+
const wrapped = decorator(getter as (this: object) => number, ctx);
|
|
1395
|
+
|
|
1396
|
+
const instance = { id: "test-instance" };
|
|
1397
|
+
wrapped.call(instance);
|
|
1398
|
+
expect(capturedInstance).toBe(instance);
|
|
1399
|
+
});
|
|
1400
|
+
});
|
|
1401
|
+
|
|
1402
|
+
// ── createAccessorDecorator — init ────────────────────────────────────────────
|
|
1403
|
+
|
|
1404
|
+
describe("createAccessorDecorator — init", () => {
|
|
1405
|
+
it("init stores the initial value that bind receives on first get", () => {
|
|
1406
|
+
let capturedInitialValue: unknown = "NOT_SET";
|
|
1407
|
+
const behavior = {
|
|
1408
|
+
bind(_inst: object, _name: string | symbol, initialValue: unknown) {
|
|
1409
|
+
capturedInitialValue = initialValue;
|
|
1410
|
+
return { get: () => initialValue };
|
|
1411
|
+
},
|
|
1412
|
+
};
|
|
1413
|
+
const decorator = createAccessorDecorator(behavior);
|
|
1414
|
+
const target = {
|
|
1415
|
+
get() { return 0; },
|
|
1416
|
+
set() { /* original */ },
|
|
1417
|
+
} as ClassAccessorDecoratorTarget<object, number>;
|
|
1418
|
+
const ctx = { kind: "accessor", name: "val" } as unknown as ClassAccessorDecoratorContext<object, number>;
|
|
1419
|
+
const result = decorator(target, ctx);
|
|
1420
|
+
|
|
1421
|
+
const instance = {};
|
|
1422
|
+
const returned = result.init!.call(instance, 42);
|
|
1423
|
+
result.get!.call(instance); // triggers bind
|
|
1424
|
+
expect(returned).toBe(42);
|
|
1425
|
+
expect(capturedInitialValue).toBe(42);
|
|
1426
|
+
});
|
|
1427
|
+
|
|
1428
|
+
it("init returns the initial value unchanged", () => {
|
|
1429
|
+
const behavior = {
|
|
1430
|
+
bind(_inst: object, _name: string | symbol, initialValue: unknown) {
|
|
1431
|
+
return { get: () => initialValue };
|
|
1432
|
+
},
|
|
1433
|
+
};
|
|
1434
|
+
const decorator = createAccessorDecorator(behavior);
|
|
1435
|
+
const target = {
|
|
1436
|
+
get() { return ""; },
|
|
1437
|
+
set() { /* original */ },
|
|
1438
|
+
} as ClassAccessorDecoratorTarget<object, string>;
|
|
1439
|
+
const ctx = { kind: "accessor", name: "s" } as unknown as ClassAccessorDecoratorContext<object, string>;
|
|
1440
|
+
const result = decorator(target, ctx);
|
|
1441
|
+
|
|
1442
|
+
const instance = {};
|
|
1443
|
+
expect(result.init!.call(instance, "hello")).toBe("hello");
|
|
1444
|
+
});
|
|
1445
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export interface AccessorBinding {
|
|
2
|
+
get: () => unknown;
|
|
3
|
+
set?: (value: unknown) => void;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface AccessorBehavior {
|
|
7
|
+
/**
|
|
8
|
+
* Called once per instance on first access. `initialValue` is the value
|
|
9
|
+
* provided by the `accessor` field initializer (e.g. `accessor count = 0`).
|
|
10
|
+
* Returns the get/set pair used by the accessor.
|
|
11
|
+
*/
|
|
12
|
+
bind(instance: object, name: string | symbol, initialValue: unknown): AccessorBinding;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function createAccessorDecorator(behavior: AccessorBehavior) {
|
|
16
|
+
return function <This extends object, V>(
|
|
17
|
+
_target: ClassAccessorDecoratorTarget<This, V>,
|
|
18
|
+
context: ClassAccessorDecoratorContext<This, V>,
|
|
19
|
+
): ClassAccessorDecoratorResult<This, V> {
|
|
20
|
+
const bindings = new WeakMap<object, AccessorBinding>();
|
|
21
|
+
const initValues = new WeakMap<object, unknown>();
|
|
22
|
+
|
|
23
|
+
function getBinding(instance: object): AccessorBinding {
|
|
24
|
+
let b = bindings.get(instance);
|
|
25
|
+
if (!b) {
|
|
26
|
+
b = behavior.bind(instance, context.name, initValues.get(instance));
|
|
27
|
+
bindings.set(instance, b);
|
|
28
|
+
}
|
|
29
|
+
return b;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
init(this: This, value: V): V {
|
|
34
|
+
initValues.set(this as object, value);
|
|
35
|
+
return value;
|
|
36
|
+
},
|
|
37
|
+
get(this: This): V {
|
|
38
|
+
return getBinding(this as object).get() as V;
|
|
39
|
+
},
|
|
40
|
+
set(this: This, value: V): void {
|
|
41
|
+
getBinding(this as object).set?.(value as unknown);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -23,6 +23,45 @@ export function createGetterDecorator(behavior: GetterBehavior) {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
export interface WritableGetterBinding {
|
|
27
|
+
get: () => unknown;
|
|
28
|
+
set?: (value: unknown) => void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface WritableGetterBehavior {
|
|
32
|
+
/**
|
|
33
|
+
* Called once per instance during construction. Returns the get/set pair
|
|
34
|
+
* that will be installed on the instance via `Object.defineProperty`.
|
|
35
|
+
* If `set` is omitted, the property is read-only at runtime (though TypeScript
|
|
36
|
+
* may still see a setter if one is declared in the class body).
|
|
37
|
+
*/
|
|
38
|
+
bind(
|
|
39
|
+
instance: object,
|
|
40
|
+
name: string | symbol,
|
|
41
|
+
original: (this: object) => unknown,
|
|
42
|
+
): WritableGetterBinding;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function createWritableGetterDecorator(behavior: WritableGetterBehavior) {
|
|
46
|
+
return function <This, T>(
|
|
47
|
+
target: (this: This) => T,
|
|
48
|
+
context: ClassGetterDecoratorContext<This, T>,
|
|
49
|
+
): (this: This) => T {
|
|
50
|
+
context.addInitializer(function (this: unknown) {
|
|
51
|
+
const instance = this as object;
|
|
52
|
+
const binding = behavior.bind(instance, context.name, target as (this: object) => unknown);
|
|
53
|
+
const descriptor: PropertyDescriptor = {
|
|
54
|
+
get: binding.get,
|
|
55
|
+
configurable: true,
|
|
56
|
+
enumerable: false,
|
|
57
|
+
};
|
|
58
|
+
if (binding.set !== undefined) descriptor.set = binding.set;
|
|
59
|
+
Object.defineProperty(instance, context.name, descriptor);
|
|
60
|
+
});
|
|
61
|
+
return target;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
26
65
|
export interface GetterObserverBehavior {
|
|
27
66
|
/**
|
|
28
67
|
* Called once per instance when the class is initialized.
|
package/src/index.ts
CHANGED
|
@@ -54,6 +54,14 @@ export {
|
|
|
54
54
|
export {
|
|
55
55
|
createGetterDecorator,
|
|
56
56
|
type GetterBehavior,
|
|
57
|
+
createWritableGetterDecorator,
|
|
58
|
+
type WritableGetterBehavior,
|
|
59
|
+
type WritableGetterBinding,
|
|
57
60
|
createGetterObserverDecorator,
|
|
58
61
|
type GetterObserverBehavior,
|
|
59
62
|
} from "./create-getter-decorator";
|
|
63
|
+
export {
|
|
64
|
+
createAccessorDecorator,
|
|
65
|
+
type AccessorBehavior,
|
|
66
|
+
type AccessorBinding,
|
|
67
|
+
} from "./create-accessor-decorator";
|