Initializable.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. /* tslint:disable:no-invalid-this */
  2. import { IInitializable } from '../interfaces/IInitializable';
  3. /**
  4. * @param {string} initializeMethodKey
  5. * @returns {any}
  6. */
  7. export function initializable (
  8. initializeMethodKey: string = 'initialize'
  9. ): (target: IInitializable, propertyKey: string | symbol) => any {
  10. const decoratorName: string = Object.keys(this)[0];
  11. return (target: IInitializable, propertyKey: string | symbol): PropertyDescriptor => {
  12. const descriptor: PropertyDescriptor = {
  13. configurable: true,
  14. enumerable: true
  15. };
  16. const initializeMethod: Function = target[initializeMethodKey];
  17. if (!initializeMethod || typeof initializeMethod !== 'function') {
  18. throw new Error(`\`${initializeMethodKey}\` method with initialization logic not found. \`@${decoratorName}\` decorator requires \`${initializeMethodKey}\` method`);
  19. }
  20. const metadataPropertyKey: string = `_${propertyKey}`;
  21. const propertyDescriptor: PropertyDescriptor = Object.getOwnPropertyDescriptor(target, metadataPropertyKey) || descriptor;
  22. const methodDescriptor: PropertyDescriptor = Object.getOwnPropertyDescriptor(target, initializeMethodKey) || descriptor;
  23. const originalMethod: Function = methodDescriptor.value;
  24. Object.defineProperty(target, propertyKey, {
  25. ...propertyDescriptor,
  26. get: function (): any {
  27. if (this[metadataPropertyKey] === undefined) {
  28. throw new Error(`Property \`${propertyKey}\` is not initialized! Initialize it first!`);
  29. }
  30. return this[metadataPropertyKey];
  31. },
  32. set: function (newVal: any): void {
  33. this[metadataPropertyKey] = newVal;
  34. }
  35. });
  36. Object.defineProperty(target, initializeMethodKey, {
  37. ...methodDescriptor,
  38. value: function (): void {
  39. originalMethod.apply(this, arguments);
  40. if (this[propertyKey]) {}
  41. }
  42. });
  43. return propertyDescriptor;
  44. };
  45. }