xref: /expo/tools/src/vendoring/devmenu/Pipe.ts (revision a272999e)
1import chalk from 'chalk';
2
3import logger from '../../Logger';
4import { Task } from './steps/Task';
5
6export type Platform = 'ios' | 'android' | 'all';
7
8export type PlatformSpecificTask = {
9  task: Task;
10  platform: Platform;
11};
12
13/**
14 * A simple task executor, which sets the working directory for all task and runs them one by one.
15 * Moreover it can start only tasks for the selected platform.
16 */
17export class Pipe {
18  private readonly platformSpecificTasks: PlatformSpecificTask[];
19  protected workingDirectory: string | undefined;
20
21  constructor() {
22    this.platformSpecificTasks = [];
23  }
24
25  public setWorkingDirectory(workingDirectory: string): this {
26    this.workingDirectory = workingDirectory;
27    return this;
28  }
29
30  /**
31   * This method accepts two types of arguments:
32   * - string - indicates the platform on which the following tasks will be registered
33   * - task
34   *
35   * ```
36   * Pipe().addSteps(
37   *    T1,
38   *    T2,
39   *  'android',
40   *    T3A,
41   *  'ios',
42   *    T3I,
43   *  'all',
44   *    T4
45   * );
46   *
47   * will resolve to:
48   * - if platform = 'all' -> [T1, T2, T3A, T3I, T4]
49   * - if platform = 'ios' -> [T1, T2, T3I, T4]
50   * - if platform = 'android' -> [T1, T2, T3A, T4]
51   * ```
52   */
53  public addSteps(...tasks: (Task | string | Task[])[]): this {
54    let currentPlatform: Platform = 'all';
55    tasks.forEach((task) => {
56      if (typeof task === 'string') {
57        currentPlatform = task as Platform;
58        return;
59      }
60
61      if (Array.isArray(task)) {
62        this.platformSpecificTasks.push(
63          ...task.map((t) => ({ platform: currentPlatform, task: t }))
64        );
65        return;
66      }
67
68      this.platformSpecificTasks.push({ platform: currentPlatform, task });
69    });
70
71    return this;
72  }
73
74  public async start(platform: Platform) {
75    logger.debug(`Staring pipe for platform = ${chalk.green(platform)}`);
76    logger.debug(
77      `${chalk.green('<workingDirectory>')} = ${chalk.yellow(this.workingDirectory || '')}`
78    );
79    logger.debug();
80
81    const tasks = this.platformSpecificTasks
82      .filter((platformSpecificStep) => {
83        const { platform: stepPlatform } = platformSpecificStep;
84        if (platform === 'all' || stepPlatform === 'all') {
85          return true;
86        }
87
88        if (platform === stepPlatform) {
89          return true;
90        }
91
92        return false;
93      })
94      .map(({ task }) => task);
95
96    for (const task of tasks) {
97      if (this.workingDirectory) {
98        task.setWorkingDirectory(this.workingDirectory);
99      }
100      await task.start();
101    }
102  }
103}
104