File

libs/nx/src/executors/journal/utils/create-journal-record.ts

Description

Transform Markdown Frontmatter Data & Decorators into individual objects for further processing.

Index

Properties

Properties

description
Type string
id
Type string
import { BuildingBlockJournalRecord } from '@allianz/taly-core/schemas';
import { tsquery } from '@phenomnomnominal/tsquery';
import { existsSync } from 'fs';
import { readFile } from 'fs/promises';
import path, { basename } from 'path';
import ts from 'typescript';
import { readMarkdownAttributes } from '../../shared/metadata-utils/read-markdown';
import { JournalLogger } from '../journal.impl';
import { BbMarkdownAttributes, validateMarkdownAttributes } from './bb-markdown-validators';
import { readAclResourceDescriptor } from './read-acl-resource-descriptor';
import { transformLobValues } from './transform-lob-values';

/**
 * Transform Markdown Frontmatter Data & Decorators
 * into individual objects for further processing.
 */

export interface BusinessEventData {
  id: string;
  description: string;
}

export async function createJournalRecord(
  dir: string,
  packageName: string,
  logger: JournalLogger
): Promise<BuildingBlockJournalRecord> {
  // from the given folder path use the folder name to guess the markdown & component file names.
  const buildingBlockBaseName = basename(dir);
  const markdownFile = path.join(dir, buildingBlockBaseName + '.md');
  const componentFile = path.join(dir, buildingBlockBaseName + '.component.ts');
  const moduleFile = path.join(dir, buildingBlockBaseName + '.module.ts');
  const aclDeclarations = path.join(dir, buildingBlockBaseName + '.acl.yml');
  // prepare all data we are interested in
  const mdAttributes: BbMarkdownAttributes = await readMarkdownAttributes(markdownFile);

  const mdValidationErrors = validateMarkdownAttributes(mdAttributes);
  if (mdValidationErrors.length) {
    logger.error('    - Markdown attribute validation errors:');
    logger.error(
      '        ' +
        mdValidationErrors
          .map((error) => `${error.error}${error.details ? ` (${error.details})` : ''}`)
          .join(', ')
    );
  }

  let selector: string | undefined;
  if (!existsSync(componentFile)) {
    logger.error(`    - Could not find component file for "${buildingBlockBaseName}"`);
  } else {
    const componentContent = (await readFile(componentFile)).toString();
    const selectorNodes = tsquery(
      componentContent,
      'Decorator:has(Identifier[name="Component"]) PropertyAssignment:has(Identifier[name="selector"]) StringLiteral'
    ) as ts.StringLiteral[];

    if (selectorNodes.length === 0) {
      logger.error(
        `    - Could not determine component selector in file "${basename(componentFile)}"`
      );
    }
    selector = selectorNodes[0]?.text as string | undefined;
  }

  let moduleName: string | undefined;
  if (!existsSync(moduleFile)) {
    logger.error(`    - Could not find module file for "${buildingBlockBaseName}"`);
  } else {
    const moduleContent = (await readFile(moduleFile)).toString();
    const moduleNodes = tsquery(
      moduleContent,
      'ClassDeclaration:has(Decorator Identifier[name="NgModule"])'
    ) as ts.ClassDeclaration[];

    if (moduleNodes.length === 0) {
      logger.error(`    - Could not determine module name in file "${basename(moduleFile)}"`);
    }
    moduleName = moduleNodes[0]?.name?.escapedText as string | undefined;
  }

  const aclDescriptor = readAclResourceDescriptor(aclDeclarations, { root: dir, logger });

  // save & return it in an object
  const id = buildingBlockBaseName;

  const isDeprecated = mdAttributes.deprecated !== undefined;

  const isDesignApproved = mdAttributes['design-approved']?.toString().toLowerCase() === 'true';

  return {
    id: id,
    title: mdAttributes.title,
    lob: transformLobValues(mdAttributes.lob),
    channel: mdAttributes.channel,
    aclDescriptor,
    selector: selector,
    validations: mdAttributes.validations,
    businessEvents: mdAttributes['business-events'],
    module: moduleName,
    package: packageName,
    designApproved: isDesignApproved,
    deprecated: isDeprecated,
    deprecationMessage: isDeprecated ? mdAttributes.deprecated?.trim() : undefined
  };
}

results matching ""

    No results matching ""