Code coverage report for src/pipeline.js

Statements: 79.31% (23 / 29)      Branches: 50% (3 / 6)      Functions: 100% (6 / 6)      Lines: 79.31% (23 / 29)      Ignored: none     

All files » src/ » pipeline.js
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      1                                                                                                                                               6   6   6               6     6   6                 6 6   1 6   6 6   6 6   1             6 6 6   6       1 18 6      
/**
* The status of a Pipeline.
*/
export const pipelineStatus = {
  completed: 'completed',
  canceled: 'canceled',
  rejected: 'rejected',
  running: 'running'
};
 
/**
* A callback to indicate when pipeline processing should advance to the next step
* or be aborted.
*/
interface Next {
  /**
  * Indicates the successful completion of the pipeline step.
  */
  (): Promise<any>,
 
  /**
  * Indicates the successful completion of the entire pipeline.
  */
  complete: (result: any) => Promise<any>,
 
  /**
  * Indicates that the pipeline should cancel processing.
  */
  cancel: (result: any) => Promise<any>,
 
  /**
  * Indicates that pipeline processing has failed and should be stopped.
  */
  reject: (result: any) => Promise<any>
}
 
/**
* A step to be run during processing of the pipeline.
*/
interface PipelineStep {
  /**
   * Execute the pipeline step. The step should invoke next(), next.complete(),
   * next.cancel(), or next.reject() to allow the pipeline to continue.
   *
   * @param instruction The navigation instruction.
   * @param next The next step in the pipeline.
   */
  run(instruction: NavigationInstruction, next: Next): void;
}
 
/**
* The result of a pipeline run.
*/
interface PipelineResult {
  status: string;
  instruction: NavigationInstruction;
  output: any;
  completed: boolean;
}
 
/**
* The class responsible for managing and processing the navigation pipeline.
*/
export class Pipeline {
  /**
  * The pipeline steps.
  */
  steps: Array<Function|PipelineStep> = [];
 
  /**
  * Adds a step to the pipeline.
  *
  * @param step The pipeline step.
  */
  addStep(step: PipelineStep): Pipeline {
    let run;
 
    Iif (typeof step === 'function') {
      run = step;
    } else Iif (typeof step.getSteps === 'function') {
      let steps = step.getSteps();
      for (let i = 0, l = steps.length; i < l; i++) {
        this.addStep(steps[i]);
      }
 
      return this;
    } else {
      run = step.run.bind(step);
    }
 
    this.steps.push(run);
 
    return this;
  }
 
  /**
  * Runs the pipeline.
  *
  * @param instruction The navigation instruction to process.
  */
  run(instruction: NavigationInstruction): Promise<PipelineResult> {
    let index = -1;
    let steps = this.steps;
 
    function next() {
      index++;
 
      Eif (index < steps.length) {
        let currentStep = steps[index];
 
        try {
          return currentStep(instruction, next);
        } catch (e) {
          return next.reject(e);
        }
      } else {
        return next.complete();
      }
    }
 
    next.complete = createCompletionHandler(next, pipelineStatus.completed);
    next.cancel = createCompletionHandler(next, pipelineStatus.canceled);
    next.reject = createCompletionHandler(next, pipelineStatus.rejected);
 
    return next();
  }
}
 
function createCompletionHandler(next, status) {
  return (output) => {
    return Promise.resolve({ status, output, completed: status === pipelineStatus.completed });
  };
}