All files / src context.ts

97.14% Statements 34/35
90.91% Branches 10/11
100% Functions 12/12
97.14% Lines 34/35
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  1x 1x 1x 1x 1x     2x 8x 8x   5x   8x 8x 8x       1x 1x 1x 1x       1x 1x 1x 1x 1x     1x     1x 2x       2x 2x             1x     1x     1x     3x 12x 6x   6x       1x                                                                
import * as matter from 'gray-matter';
import kebabCase = require('lodash.kebabcase');
import * as path from 'path';
import {formatMatter} from './helpers';
 
export class Context {
  public static toKebabProps(
    obj: {[p: string]: any},
    ignoreProps?: string[],
  ): object {
    return Object.keys(obj).reduce(
      ([data, propMap], originalKey) => {
        let key = originalKey;
        if (
          ignoreProps === undefined ||
          (ignoreProps !== undefined && ignoreProps.indexOf(key) === -1)
        ) {
          key = kebabCase(originalKey);
        }
        propMap[key] = originalKey;
        data[key] = obj[originalKey];
        return [data, propMap];
      },
      [{}, {}] as [{[p: string]: any}, {[p: string]: any}],
    );
  }
 
  public filename: string;
  public scope: ContextScope;
  public config?: {
    filename?: string;
    description?: string;
    usage?: string;
  };
  public note?: string;
  public data: ContextData;
  public content: string;
  private propMap: {[prop: string]: any};
 
  constructor(filename: string, content: string, scope: ContextScope) {
    const ctx = formatMatter(matter(content));
    this.filename = filename;
    this.scope = scope;
    const [data, propMap] = Context.toKebabProps(ctx.data, [
      'CONFIG',
      'NOTE',
    ]) as [ContextData, object];
    this.config = (ctx.data as any).CONFIG;
    this.note = (ctx.data as any).NOTE;
    this.data = data;
    this.propMap = propMap;
    this.content = ctx.content;
  }
 
  public getOriginalProp(prop: string): string {
    return this.propMap[prop];
  }
 
  public forEachFlag(cb: (flag: string, data: matter.Options) => void) {
    this.flags.forEach(flag => {
      cb(flag, this.data[flag]);
    });
  }
 
  private getData(flag: ContextConfigType): matter.Options | string | false {
    try {
      return this.config![flag] || false;
    } catch (_) {
      return false;
    }
  }
 
  public get commandName() {
    return path.basename(this.filename, '.hbs');
  }
 
  public get description(): string | undefined {
    return this.getData('description') as string;
  }
 
  public get usage(): string | undefined {
    return this.getData('usage') as string;
  }
 
  public get flags(): string[] {
    return Object.keys(this.data).filter(flag => {
      if (flag === 'CONFIG' || flag === 'NOTE') {
        return false;
      }
      return true;
    });
  }
}
 
export type ContextScope = 'global' | 'local';
export type ContextConfigType = 'filename' | 'description' | 'usage';
export interface ContextData {
  [flag: string]: matter.Options;
}