tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

projects.mjs (5257B)


      1 /**
      2 * @license
      3 * Copyright 2023 Google Inc.
      4 * SPDX-License-Identifier: Apache-2.0
      5 */
      6 
      7 import {spawn} from 'child_process';
      8 import {randomUUID} from 'crypto';
      9 import {readFile, writeFile} from 'fs/promises';
     10 import {join} from 'path';
     11 import {cwd} from 'process';
     12 
     13 class AngularProject {
     14  static ports = new Set();
     15  static randomPort() {
     16    /**
     17     * Some ports are restricted by Chromium and will fail to connect
     18     * to prevent we start after the
     19     *
     20     * https://source.chromium.org/chromium/chromium/src/+/main:net/base/port_util.cc;l=107?q=kRestrictedPorts&ss=chromium
     21     */
     22    const min = 10101;
     23    const max = 20202;
     24    return Math.floor(Math.random() * (max - min + 1) + min);
     25  }
     26  static port() {
     27    const port = AngularProject.randomPort();
     28    if (AngularProject.ports.has(port)) {
     29      return AngularProject.port();
     30    }
     31    return port;
     32  }
     33 
     34  static #scripts = testRunner => {
     35    return {
     36      // Builds the ng-schematics before running them
     37      'build:schematics': 'npm run --prefix ../../ build',
     38      // Deletes all files created by Puppeteer Ng-Schematics to avoid errors
     39      'delete:file':
     40        'rm -f .puppeteerrc.cjs && rm -f tsconfig.e2e.json && rm -R -f e2e/',
     41      // Runs the Puppeteer Ng-Schematics against the sandbox
     42      schematics: 'schematics ../../:ng-add --dry-run=false',
     43      'schematics:e2e': 'schematics ../../:e2e --dry-run=false',
     44      'schematics:config': 'schematics ../../:config --dry-run=false',
     45      'schematics:add': `schematics ../../:ng-add --dry-run=false --test-runner="${testRunner}"`,
     46      'schematics:smoke': 'ng e2e',
     47    };
     48  };
     49  /** Folder name */
     50  #name;
     51  /** E2E test runner to use */
     52  #runner;
     53 
     54  type = '';
     55 
     56  constructor(runner, name) {
     57    this.#runner = runner ?? 'node';
     58    this.#name = name ?? randomUUID();
     59  }
     60 
     61  get runner() {
     62    return this.#runner;
     63  }
     64 
     65  get name() {
     66    return this.#name;
     67  }
     68 
     69  async executeCommand(command, options) {
     70    const [executable, ...args] = command.split(' ');
     71    await new Promise((resolve, reject) => {
     72      const createProcess = spawn(executable, args, {
     73        shell: true,
     74        ...options,
     75      });
     76 
     77      const onData = data => {
     78        data = data
     79          .toString()
     80          // Replace new lines with a prefix including the test runner
     81          .replace(
     82            /(?:\r\n?|\n)(?=.*[\r\n])/g,
     83            `\n${this.#runner}:${this.type} - `,
     84          );
     85        console.log(`${this.#runner}:${this.type} - ${data}`);
     86      };
     87 
     88      createProcess.stdout.on('data', onData);
     89      createProcess.stderr.on('data', onData);
     90 
     91      createProcess.on('error', message => {
     92        console.error(`Running ${command} exited with error:`, message);
     93        reject(message);
     94      });
     95 
     96      createProcess.on('exit', code => {
     97        if (code === 0) {
     98          resolve(true);
     99        } else {
    100          reject();
    101        }
    102      });
    103    });
    104  }
    105 
    106  async create() {
    107    await this.createProject();
    108    await this.updatePackageJson();
    109  }
    110 
    111  async updatePackageJson() {
    112    const packageJsonFile = join(cwd(), `/sandbox/${this.#name}/package.json`);
    113    const packageJson = JSON.parse(await readFile(packageJsonFile));
    114    packageJson['scripts'] = {
    115      ...packageJson['scripts'],
    116      ...AngularProject.#scripts(this.#runner),
    117    };
    118    await writeFile(packageJsonFile, JSON.stringify(packageJson, null, 2));
    119  }
    120 
    121  get commandOptions() {
    122    return {
    123      ...process.env,
    124      cwd: join(cwd(), `/sandbox/${this.#name}/`),
    125    };
    126  }
    127 
    128  async runNpmScripts(command, options) {
    129    await this.executeCommand(`npm run ${command}`, {
    130      ...this.commandOptions,
    131      options,
    132    });
    133  }
    134 
    135  async runSchematics() {
    136    await this.runNpmScripts('schematics');
    137  }
    138 
    139  async runSchematicsE2E() {
    140    await this.runNpmScripts('schematics:e2e');
    141  }
    142 
    143  async runSchematicsConfig() {
    144    await this.runNpmScripts('schematics:config');
    145  }
    146 
    147  async runNgAdd() {
    148    await this.runNpmScripts(
    149      `schematics:add -- --port=${AngularProject.port()}`,
    150    );
    151  }
    152 
    153  async runSmoke() {
    154    await this.runNpmScripts(
    155      `schematics:smoke -- --port=${AngularProject.port()}`,
    156    );
    157  }
    158 }
    159 
    160 export class AngularProjectSingle extends AngularProject {
    161  type = 'single';
    162 
    163  async createProject() {
    164    await this.executeCommand(
    165      `ng new ${this.name} --directory=sandbox/${this.name} --defaults --skip-git`,
    166      {
    167        env: {
    168          PUPPETEER_SKIP_DOWNLOAD: 'true',
    169          ...process.env,
    170        },
    171      },
    172    );
    173  }
    174 }
    175 
    176 export class AngularProjectMulti extends AngularProject {
    177  type = 'multi';
    178 
    179  async createProject() {
    180    await this.executeCommand(
    181      `ng new ${this.name} --create-application=false --directory=sandbox/${this.name} --defaults --skip-git`,
    182      {
    183        env: {
    184          PUPPETEER_SKIP_DOWNLOAD: 'true',
    185          ...process.env,
    186        },
    187      },
    188    );
    189 
    190    await this.executeCommand(
    191      `ng generate application core --style=css --routing=true`,
    192      {
    193        PUPPETEER_SKIP_DOWNLOAD: 'true',
    194        ...this.commandOptions,
    195      },
    196    );
    197    await this.executeCommand(
    198      `ng generate application admin --style=css --routing=false`,
    199      {
    200        PUPPETEER_SKIP_DOWNLOAD: 'true',
    201        ...this.commandOptions,
    202      },
    203    );
    204  }
    205 }