All files / src/class compiler.ts

74.29% Statements 26/35
50% Branches 5/10
90% Functions 9/10
77.42% Lines 24/31

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 8315x 15x 15x 15x 15x 15x                           15x     8x     8x   16x       21x       10x       13x       5x 5x   5x         5x                           5x   5x 5x   5x       3x       5x 5x      
import EventEmitter from 'events'
import { mergeDeepLeft, pick, prop } from 'ramda'
import { join } from 'path'
import { CheckOptions, Resource, Effect } from '@/internal'
import yaml from 'js-yaml'
import { logger } from '@/utils'
import { Template } from './template'
import { Project } from './project'
 
 
export interface RenderOptions {
  /**
   * always prompt the question,
   * even though it was answered.
   */
  ignoreAnswered?: boolean
}
 
 
export class Compiler {
  public readonly resource: Resource
 
  private readonly eventEmitter: EventEmitter = new EventEmitter()
 
  constructor(resource: Resource) {
    this.resource = resource
 
    this.template.hooks.map(hook => hook.appendTo(this.eventEmitter))
  }
 
  get template(): Template {
    return this.resource.template
  }
 
  get project(): Project {
    return this.resource.project
  }
 
  public emit(name: string): void {
    this.eventEmitter.emit(name)
  }
 
  private async prompt(force = false): Promise<void> {
    const { template, project } = this
    let { questions } = template
 
    Iif (project.answers && !force) {
      const answers = project.answers
      questions = questions.filter(question => !question.answered(answers))
    }
 
    Eif (!questions.length) return
 
    logger.info('Please answer the questions of template.')
 
    const namesOfQuestions = questions.map(prop('name'))
    let answers = await Effect.prompter(questions)
 
    if (project.answers) answers = mergeDeepLeft(answers, project.answers)
 
 
    project.answers = pick(namesOfQuestions, answers)
  }
 
  public async render(options: RenderOptions = {}): Promise<void> {
    await this.prompt(options.ignoreAnswered)
 
    await this.template.render(this.resource)
    await this.generateMilirc()
 
    this.emit('rendered')
  }
 
  public async check(options: CheckOptions): Promise<void> {
    await this.template.check(this.resource, options)
  }
 
  private async generateMilirc(): Promise<void> {
    const milirc = yaml.safeDump(this.resource.milirc, { skipInvalid: true })
    await Effect.fs.writeFile(join(this.project.path, '.milirc.yml'), milirc, 'utf8')
  }
}