All files / src/context/directory/handlers pages.ts

89.13% Statements 41/46
85% Branches 17/20
100% Functions 5/5
90.24% Lines 37/41

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 98 991x 1x 1x   1x 1x                 61x 61x   3x             3x 18x 18x 18x 18x 18x     3x 10x 10x       10x   2x               8x       8x                       3x           2x   2x   2x 2x   2x 5x   5x 3x 3x 3x 3x     5x 5x       1x         1x  
import fs from 'fs-extra';
import path from 'path';
import { constants, loadFileAndReplaceKeywords } from '../../../tools';
 
import log from '../../../logger';
import { getFiles, existsMustBeDir, dumpJSON, loadJSON } from '../../../utils';
import { DirectoryHandler } from '.';
import DirectoryContext from '..';
import { ParsedAsset } from '../../../types';
import { Page } from '../../../tools/auth0/handlers/pages';
 
type ParsedPages = ParsedAsset<'pages', Page[]>;
 
function parse(context: DirectoryContext): ParsedPages {
  const pagesFolder = path.join(context.filePath, constants.PAGES_DIRECTORY);
  if (!existsMustBeDir(pagesFolder)) return { pages: null }; // Skip
 
  const files: string[] = getFiles(pagesFolder, ['.json', '.html']);
 
  const sorted: {
    [key: string]: {
      meta?: string;
      html?: string;
    };
  } = files.reduce((acc, file) => {
    const { ext, name } = path.parse(file);
    if (!acc[name]) acc[name] = {};
    if (ext === '.json') acc[name].meta = file;
    if (ext === '.html') acc[name].html = file;
    return acc;
  }, {});
 
  const pages = Object.keys(sorted).flatMap((key): Page[] => {
    const { meta, html } = sorted[key];
    Iif (!meta) {
      log.warn(`Skipping pages file ${html} as missing the corresponding '.json' file`);
      return [];
    }
    if (!html && ['error_page', 'login'].includes(key)) {
      //Error pages don't require an HTML template, it is valid to redirect errors to URL
      return {
        ...loadJSON(meta, {
          mappings: context.mappings,
          disableKeywordReplacement: context.disableKeywordReplacement,
        }),
        html: '',
      };
    }
    Iif (!html) {
      log.warn(`Skipping pages file ${meta} as missing corresponding '.html' file`);
      return [];
    }
    return {
      ...loadJSON(meta, {
        mappings: context.mappings,
        disableKeywordReplacement: context.disableKeywordReplacement,
      }),
      html: loadFileAndReplaceKeywords(html, {
        mappings: context.mappings,
        disableKeywordReplacement: context.disableKeywordReplacement,
      }),
    };
  });
 
  return {
    pages,
  };
}
 
async function dump(context: DirectoryContext): Promise<void> {
  const pages = context.assets.pages;
 
  Iif (!pages) return;
 
  const pagesFolder = path.join(context.filePath, constants.PAGES_DIRECTORY);
  fs.ensureDirSync(pagesFolder);
 
  pages.forEach((page) => {
    const metadata = { ...page };
 
    if (page.html !== undefined) {
      const htmlFile = path.join(pagesFolder, `${page.name}.html`);
      log.info(`Writing ${htmlFile}`);
      fs.writeFileSync(htmlFile, page.html);
      metadata.html = `./${page.name}.html`;
    }
 
    const pageFile = path.join(pagesFolder, `${page.name}.json`);
    dumpJSON(pageFile, metadata);
  });
}
 
const pagesHandler: DirectoryHandler<ParsedPages> = {
  parse,
  dump,
};
 
export default pagesHandler;