All files / src/lib/engine decorators.ts

91.66% Statements 11/12
0% Branches 0/1
100% Functions 2/2
91.66% Lines 11/12

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 9810x 10x 10x 10x 10x 10x                                                   10x 37x   37x   37x         37x                                                                                                                
import { apply, metadata } from '@decaf-ts/decoration';
import { NgxRenderingEngine } from './NgxRenderingEngine';
import { AngularEngineKeys } from './constants';
import { Constructor, Metadata } from '@decaf-ts/decoration';
import { InternalError } from '@decaf-ts/db-decorators';
import { reflectComponentType, Type } from '@angular/core';
 
/**
 * @description Marks an Angular component as dynamically loadable
 * @summary Decorator that registers an Angular component with the NgxRenderingEngine for dynamic loading.
 * This decorator must be applied before the @Component decorator to properly extract component metadata.
 * It adds metadata to the component class and registers it with the rendering engine using its selector.
 * @function Dynamic
 * @return {Function} A decorator function that can be applied to Angular component classes
 * @mermaid
 * sequenceDiagram
 *   participant C as Component Class
 *   participant D as Dynamic Decorator
 *   participant R as NgxRenderingEngine
 *   participant M as Angular Metadata
 *   C->>D: Apply decorator
 *   D->>M: reflectComponentType()
 *   M-->>D: Return component metadata
 *   alt No metadata found
 *     D->>D: Throw InternalError
 *   else Metadata found
 *     D->>R: registerComponent(selector, constructor)
 *     D->>C: Apply metadata
 *   end
 * @category Decorators
 */
export function Dynamic() {
  return apply(
    (original: object) => {
      const metadata = reflectComponentType(original as Type<unknown>);
 
      Iif (!metadata)
        throw new InternalError(
          `Could not find Component metadata. @Dynamic decorator must come above @Component`
        );
 
      NgxRenderingEngine.registerComponent(
        metadata.selector,
        original as unknown as Constructor<unknown>
      );
    },
    metadata(
      Metadata.key(AngularEngineKeys.REFLECT, AngularEngineKeys.DYNAMIC),
      true
    )
  );
}
 
 
//TODO: Create dynamic decorator to store props on parents and load on childs
// import { Input, signal } from '@angular/core';
 
// export function dynamic() {
//   return function (target: any, propertyKey: string) {
 
//     // Marca como Input automaticamente
 
//     // Armazena a lista de propriedades decoradas
//     if (!target.__initPropsList)
//       target.__initPropsList = [];
 
//     target.__initPropsList.push(propertyKey);
 
//     // Patch no ngOnInit apenas uma vez
//     if (!target.__initPropsPatched) {
//       target.__initPropsPatched = true;
 
//       const originalOnInit = target.ngOnInit;
 
//       target.ngOnInit = function () {
 
//         // Cria o signal __props no componente
//         this._props = signal({});
 
//         const collected: any = {};
 
//         // Coleta todas as propriedades decoradas
//         for (const key of this.__initPropsList) {
//           collected[key] = this[key];
//         }
 
//         // Atualiza o signal
//         this._props.set(collected);
 
//         // Chama o ngOnInit original, se existir
//         if (originalOnInit) {
//           originalOnInit.apply(this);
//         }
//       };
//     }
//   };
// }