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

97.5% Statements 39/40
93.75% Branches 15/16
100% Functions 5/5
100% Lines 38/38

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 99 100 101 1021x 1x 1x   1x 1x                                   58x 58x 58x   4x   4x   6x         6x 2x 2x   2x 1x       1x           5x   5x   3x           3x   3x   3x 3x     3x 5x             5x   5x 1x 1x 1x   1x 1x   1x     5x 5x       1x         1x  
import fs from 'fs-extra';
import path from 'path';
import { constants, loadFileAndReplaceKeywords } from '../../../tools';
 
import log from '../../../logger';
import {
  isFile,
  getFiles,
  existsMustBeDir,
  dumpJSON,
  loadJSON,
  sanitize,
  ensureProp,
  mapClientID2NameSorted,
} from '../../../utils';
import { DirectoryHandler } from '.';
import DirectoryContext from '..';
import { Asset, ParsedAsset } from '../../../types';
 
type ParsedConnections = ParsedAsset<'connections', Asset[]>;
 
function parse(context: DirectoryContext): ParsedConnections {
  const connectionDirectory =
    context.config.AUTH0_CONNECTIONS_DIRECTORY || constants.CONNECTIONS_DIRECTORY;
  const connectionsFolder = path.join(context.filePath, connectionDirectory);
  if (!existsMustBeDir(connectionsFolder)) return { connections: null }; // Skip
 
  const foundFiles = getFiles(connectionsFolder, ['.json']);
 
  const connections = foundFiles
    .map((f) => {
      const connection = loadJSON(f, {
        mappings: context.mappings,
        disableKeywordReplacement: context.disableKeywordReplacement,
      });
 
      if (connection.strategy === 'email') {
        ensureProp(connection, 'options.email.body');
        const htmlFileName = path.join(connectionsFolder, connection.options.email.body);
 
        if (!isFile(htmlFileName)) {
          throw new Error(
            `Passwordless email template purportedly located at ${htmlFileName} does not exist for connection. Ensure the existence of this file to proceed with deployment.`
          );
        }
        connection.options.email.body = loadFileAndReplaceKeywords(htmlFileName, {
          mappings: context.mappings,
          disableKeywordReplacement: context.disableKeywordReplacement,
        });
      }
 
      return connection;
    })
    .filter((p) => Object.keys(p).length > 0); // Filter out empty connections
 
  return {
    connections,
  };
}
 
async function dump(context: DirectoryContext): Promise<void> {
  const { connections, clientsOrig } = context.assets;
 
  Iif (!connections) return; // Skip, nothing to dump
 
  const connectionsFolder = path.join(context.filePath, constants.CONNECTIONS_DIRECTORY);
  fs.ensureDirSync(connectionsFolder);
 
  // Convert enabled_clients from id to name
  connections.forEach((connection) => {
    const dumpedConnection = {
      ...connection,
      ...(connection.enabled_clients && {
        enabled_clients: mapClientID2NameSorted(connection.enabled_clients, clientsOrig || []),
      }),
    };
 
    const connectionName = sanitize(dumpedConnection.name);
 
    if (dumpedConnection.strategy === 'email') {
      ensureProp(dumpedConnection, 'options.email.body');
      const html = dumpedConnection.options.email.body;
      const emailConnectionHtml = path.join(connectionsFolder, `${connectionName}.html`);
 
      log.info(`Writing ${emailConnectionHtml}`);
      fs.writeFileSync(emailConnectionHtml, html);
 
      dumpedConnection.options.email.body = `./${connectionName}.html`;
    }
 
    const connectionFile = path.join(connectionsFolder, `${connectionName}.json`);
    dumpJSON(connectionFile, dumpedConnection);
  });
}
 
const connectionsHandler: DirectoryHandler<ParsedConnections> = {
  parse,
  dump,
};
 
export default connectionsHandler;