All files / src/utils/backbase eslint.ts

56% Statements 28/50
18.75% Branches 3/16
50% Functions 4/8
56.25% Lines 27/48

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 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142  22x 22x   22x 22x                                               22x   10x   10x 10x           22x       22x 6x   6x       6x 6x     22x                                                                                                                 22x 2x 2x 2x               2x 4x 2x   4x   4x     2x         2x   2x    
import { Tree } from '@angular-devkit/schematics';
import { view, lensPath } from 'ramda';
import { readFileOrThrow } from './package-utils';
 
const DEFAULT_PREFIX = 'bb';
const ESLINT_PATH = '/.eslintrc.json';
 
type action = string;
type elementOrAttribute = 'element' | 'attribute';
type prefix = string | string[];
type capCase = 'kebab-case' | 'camelCase';
type elementRule = {
  prefix: prefix;
  style: capCase;
  type: elementOrAttribute;
};
type files = '*.ts' | '*.html';
 
type selectorRule = [action, elementRule];
interface EsLint {
  overrides: {
    files: [files];
    rules: {
      '@angular-eslint/component-selector'?: selectorRule;
      '@angular-eslint/directive-selector'?: selectorRule;
    };
  }[];
}
 
export const getEsLint = (tree: Tree): EsLint => {
  // @todo: don't throw if no tslint?
  const tslintSource = readFileOrThrow(tree, ESLINT_PATH);
 
  try {
    return JSON.parse(tslintSource);
  } catch (err) {
    throw new Error(`Couldn't parse tslint. Invalid JSON: ${err}`);
  }
};
 
const getComponentSelector: (tslint: EsLint) => selectorRule | undefined = view<EsLint, selectorRule | undefined>(
  lensPath(['overrides', 0, 'rules', '@angular-eslint/component-selector']),
);
 
export function getDefaultPrefix(tree: Tree): string {
  const componentSelector = getComponentSelector(getEsLint(tree));
 
  Iif (!componentSelector) {
    return DEFAULT_PREFIX;
  }
 
  const prefix = componentSelector[1].prefix;
  return Array.isArray(prefix) ? prefix[0] || DEFAULT_PREFIX : prefix;
}
 
export function addESslintPrefix(prefix: string) {
  const isSelectorRule = (value: any): value is selectorRule => Array.isArray(value) && value.length === 4;
 
  const updateTslintPrefix = (
    ruleName: '@angular-eslint/component-selector' | '@angular-eslint/directive-selector',
    eslint: EsLint,
  ): EsLint => {
    const selectorRule = eslint.overrides[0].rules && eslint.overrides[0].rules[ruleName];
    Iif (!isSelectorRule(selectorRule)) {
      return eslint;
    }
 
    const existingPrefix = selectorRule[1].prefix;
    const existingPrefixArray = Array.isArray(existingPrefix) ? existingPrefix : [existingPrefix];
    Iif (existingPrefixArray.includes(prefix)) {
      return eslint; // already set, no need to update
    }
 
    const newComponentSelector: selectorRule = [
      selectorRule[0],
 
      {
        ...selectorRule[1],
        prefix: [...existingPrefixArray, prefix],
      },
    ];
 
    const newEsLint = {
      ...eslint,
      overrides: [
        {
          ...eslint.overrides[0],
          rules: {
            ...eslint.overrides[0].rules,
            [ruleName]: newComponentSelector,
          },
        },
        ...eslint.overrides.slice(1, eslint.overrides.length),
      ],
    };
    return newEsLint;
  };
 
  return (tree: Tree): Tree => {
    const tslint = getEsLint(tree);
    const newTsLint = updateTslintPrefix(
      '@angular-eslint/component-selector',
      updateTslintPrefix('@angular-eslint/directive-selector', tslint),
    );
    Iif (tslint === newTsLint) {
      return tree; // wasn't modified
    }
    tree.overwrite(ESLINT_PATH, JSON.stringify(newTsLint, null, 2));
    return tree;
  };
}
 
export function updateEslintOverridesRules(tree: Tree, filesType: files, updatedRule?: any) {
  const eslint = getEsLint(tree);
  if (eslint) {
    const newOverridden = {
      ...eslint.overrides[0],
      rules: {
        ...eslint.overrides[0].rules,
        ...updatedRule,
      },
    };
 
    const finalOverride = [...eslint.overrides].reduce((final, overridden) => {
      if (overridden.files.includes(filesType)) {
        overridden = { ...overridden, ...newOverridden };
      }
      final.push(overridden);
 
      return final;
    }, [] as any);
 
    const newEsLint = {
      ...eslint,
      overrides: [...finalOverride],
    };
 
    tree.overwrite(ESLINT_PATH, JSON.stringify(newEsLint, null, 2));
  }
  return tree;
}