File

libs/sdk/src/lib/journey/config/migrations/classic-journey/pages-json.ts

Extends

PluginConfiguration

Index

Properties

Properties

version
Type string
import {
  BuildingBlockConfiguration,
  LibraryConfiguration,
  PluginConfiguration
} from '@allianz/taly-core/schemas';
import chalk from 'chalk';
import { PagesJsonSchema } from '../../../../model';
import { cloneDeepWithJsonComments } from '../shared/utils';

interface PluginConfigWithLibVersion extends PluginConfiguration {
  version: string;
}

function isPluginConfigWithLibVersion(
  library: PluginConfiguration | PluginConfigWithLibVersion
): library is PluginConfigWithLibVersion {
  return (library as PluginConfigWithLibVersion).version !== undefined;
}

export function migratePluginLibrariesToLibraries(pagesConfiguration: PagesJsonSchema) {
  if (!pagesConfiguration.plugins || pagesConfiguration.plugins.length === 0) {
    return pagesConfiguration;
  }

  const pluginLibrariesWithVersion: LibraryConfiguration[] = pagesConfiguration.plugins
    .filter(isPluginConfigWithLibVersion)
    .map((library) => ({
      package: removeSecondaryEntryPoint(library.package),
      version: library.version
    }));

  if (pluginLibrariesWithVersion.length === 0) {
    return pagesConfiguration;
  }

  const updatedLibrariesList = pagesConfiguration.libraries.map((library) => {
    const libraryVersion =
      pluginLibrariesWithVersion.find((lib) => lib.package === library.package)?.version ||
      library.version;

    return {
      package: library.package,
      version: libraryVersion
    };
  });

  pluginLibrariesWithVersion.forEach((library) => {
    const isLibraryInLibraries = Boolean(
      updatedLibrariesList.find((lib) => lib.package === library.package)
    );

    if (!isLibraryInLibraries) {
      updatedLibrariesList.push(library);
    }
  });

  const updatedPagesConfiguration = cloneDeepWithJsonComments(pagesConfiguration);

  updatedPagesConfiguration.libraries = updatedLibrariesList;

  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  updatedPagesConfiguration.plugins = updatedPagesConfiguration.plugins!.map((plugin) => {
    if (isPluginConfigWithLibVersion(plugin)) {
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      const { version, ...rest } = plugin;

      return rest;
    }
    return plugin;
  });

  return updatedPagesConfiguration;
}

export function moveStageConfigFromPageDataToTitle(
  pagesConfiguration: PagesJsonSchema
): PagesJsonSchema {
  const result = cloneDeepWithJsonComments(pagesConfiguration);
  result.pages
    // pageData.stage does not exist in the new schema
    // so we "need" to use `any` assertions here
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    .filter((page) => (page.pageData as any)?.stage)
    // the types (old vs. new) get in our way here, so we treat the page as "any"
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    .forEach((page: any) => {
      // ensure the title is an object
      if (typeof page.title === 'string') {
        page.title = { headline: page.title };
      }
      page.title ??= {};

      const pageData = page.pageData;
      // move the stage configuration into the pages title object
      const { subHeadline, headline, ...stageConfig } = pageData.stage;
      page.title = {
        ...page.title,
        showAsStage: true,
        ...stageConfig,
        ...(subHeadline !== undefined
          ? { topline: migrateSInterpolationToCurlyBraceInterpolation(subHeadline) }
          : {}),
        ...(headline !== undefined
          ? { headline: migrateSInterpolationToCurlyBraceInterpolation(headline) }
          : {
              headline:
                page.title.headline ??
                '⚠️ PLACEHOLDER FOR THE HEADLINE SET BY A TALY MIGRATION. REPLACE ME! ⚠️'
            })
      };

      delete pageData.stage;
      if (Object.keys(pageData).length === 0) {
        delete page.pageData;
      }
    });
  return result;
}

export function makeStickyBuildingBlockTheBannerBlock(
  pagesConfiguration: PagesJsonSchema
): PagesJsonSchema {
  const result = cloneDeepWithJsonComments(pagesConfiguration);
  result.pages.forEach((page) => {
    if (!page.blocks || page.blocks.length === 0) {
      return;
    }

    // why do we ignore errors/warnings in the following lines?
    // the new schema does not have a sticky property in the bbStyle, so we cast to any

    // general upfront cleanup: remove any `sticky: false` property
    const explicitlyNonstickyBlocks = page.blocks.filter(
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (block) => ((block as BuildingBlockConfiguration).buildingBlockStyle as any)?.sticky === false
    );
    explicitlyNonstickyBlocks.forEach((block) => {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      delete ((block as BuildingBlockConfiguration).buildingBlockStyle as any).sticky;

      // also delete the entire buildingBlockStyle if it is empty now
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
      if (Object.keys((block as BuildingBlockConfiguration).buildingBlockStyle!).length === 0) {
        delete (block as BuildingBlockConfiguration).buildingBlockStyle;
      }
    });

    const stickyBlocks = page.blocks.filter(
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (block) => ((block as BuildingBlockConfiguration).buildingBlockStyle as any)?.sticky === true
    );
    if (stickyBlocks.length === 0) {
      return;
    }
    if (stickyBlocks.length > 1) {
      console.error(
        chalk.red(
          `Only one sticky Building Block is allowed per page. Please migrate the page "${chalk.bold(
            page.id
          )}" manually.`
        )
      );
      return;
    }

    page.bannerBlock = cloneDeepWithJsonComments(stickyBlocks[0]) as BuildingBlockConfiguration;

    // delete the sticky property from the buildingBlockStyle
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    delete (page.bannerBlock.buildingBlockStyle as any).sticky;
    // also delete the entire buildingBlockStyle if it is empty now
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
    if (Object.keys(page.bannerBlock.buildingBlockStyle!).length === 0) {
      delete page.bannerBlock.buildingBlockStyle;
    }

    page.blocks = page.blocks.filter((block) => block !== stickyBlocks[0]);
  });
  return result;
}

/**
 * This function will remove anything that looks like a secondary entry point from a package name.
 * It works for scoped packages as well as unscoped packages.
 *
 * | Input | Output |
 * | :---- | :----- |
 * | `@scope/package` | `@scope/package` |
 * | `@scope/package/entry-point` | `@scope/package` |
 * | `package` | `package` |
 * | `package/entry-point` | `package` |
 *
 * @param packageName the package name to remove the secondary entry point from
 */
function removeSecondaryEntryPoint(packageName: string): string {
  const endIndex = packageName.startsWith('@') ? 2 : 1;
  return packageName.split('/').slice(0, endIndex).join('/');
}

function migrateSInterpolationToCurlyBraceInterpolation(source: string): string {
  const resourcesMatcher = /s\(["'](.*?)["']\)/g;
  const resourcesReplacer = '{$1}';
  return source.replace(resourcesMatcher, resourcesReplacer);
}

results matching ""

    No results matching ""