File

libs/nx/src/executors/extract-plugin-metadata/compat/utils/inspect-injectable-class.ts

Index

Properties

Properties

injectableClassData
Type InjectableMetadata
pluginType
Type PluginType
import { InjectableMetadata, PluginType } from '@allianz/taly-core/schemas';
import { Logger } from '@angular-devkit/core/src/logger';
import { posix } from 'path';
import ts from 'typescript';
import { IntrospectionContext } from '../../../shared/introspection/types';
import { ensurePosixPathSeparators } from '../../../shared/metadata-utils/windows-compat';
import { findImplementedInterface } from './find-implemented-interface';
import { findInjectableClassFactory } from './find-injectable-class';

export interface injectableFileInspectionResult {
  injectableClassData: InjectableMetadata;
  pluginType: PluginType;
}

export const inspectInjectableClassFactory =
  (introspectionContext: IntrospectionContext, projectPath: string) =>
  (fileName: string): injectableFileInspectionResult | undefined => {
    const { injectableClassNode, injectableClassSymbol } =
      findInjectableClassFactory(introspectionContext)(fileName);

    if (!injectableClassNode || !injectableClassSymbol) {
      return undefined;
    }

    const pluginType = extractPluginType(introspectionContext.checker, injectableClassNode);

    let pluginValidatorData = {};
    if (pluginType === 'Validator') {
      pluginValidatorData = extractPluginValidatorData(
        fileName,
        injectableClassNode,
        introspectionContext.logger
      );
    }

    return {
      injectableClassData: {
        file: posix.relative(
          ensurePosixPathSeparators(projectPath),
          ensurePosixPathSeparators(fileName)
        ),
        className: injectableClassSymbol.getName(),
        ...pluginValidatorData
      },
      pluginType
    };
  };

function extractPluginType(checker: ts.TypeChecker, classNode: ts.ClassDeclaration) {
  const baseInterfaceNode = findImplementedInterface(classNode);

  if (!baseInterfaceNode) {
    return PluginType.Other;
  }

  const baseInterfaceName = checker.getSymbolAtLocation(baseInterfaceNode.expression)?.getName();

  if (baseInterfaceName === 'PluginValidator' || baseInterfaceName === 'AsyncPluginValidator') {
    return PluginType.Validator;
  } else if (baseInterfaceName === PluginType.HTTPInterceptor) {
    return PluginType.HTTPInterceptor;
  }

  return PluginType.Other;
}

function extractPluginValidatorData(
  fileName: string,
  classNode: ts.ClassDeclaration,
  logger: Logger
) {
  let validatorTypeField;
  let validationParam: ts.ParameterDeclaration | undefined;
  let validationParamType;

  classNode.members?.forEach((classElement: ts.ClassElement) => {
    if (ts.isPropertyDeclaration(classElement) && classElement.name.getText() === 'type') {
      const init = classElement.initializer as ts.Node;
      if (ts.isStringLiteral(init)) {
        validatorTypeField = init.text;
      }
    }

    if (ts.isMethodDeclaration(classElement)) {
      const validationMethods = ['validate', 'validateAsync'];
      if (validationMethods.includes(classElement.name.getText())) {
        validationParam = classElement.parameters[0];
      }
    }
  });

  if (!validatorTypeField) {
    logger.error(`Error: "type" field is missing on validator implementation`);
  }

  if (validationParam) {
    validationParamType = validationParam.type?.getText();
    if (!validationParamType) {
      logger.error(`Error: no type specified for validator method parameter`);
    }
  }

  return {
    validation: {
      validatorTypeField,
      validationParam: validationParamType
    }
  };
}

results matching ""

    No results matching ""