Replace minimist, convert build scripts to ES modules + misc refactoring

This commit is contained in:
hensm
2022-08-19 03:09:59 +01:00
parent 170b80283d
commit a186570dc8
17 changed files with 702 additions and 505 deletions

146
README.md
View File

@@ -19,10 +19,9 @@ The bridge application is currently supported on Windows, macOS and Linux.
**Note**: These packages are maintained by third parties and support likely will not be provided for any issues specific to these packages. **Note**: These packages are maintained by third parties and support likely will not be provided for any issues specific to these packages.
- **Arch Linux (AUR)** - **Arch Linux (AUR)**
- `fx_cast` — https://aur.archlinux.org/packages/fx_cast - `fx_cast` — https://aur.archlinux.org/packages/fx_cast
- `fx_cast-bin` — https://aur.archlinux.org/packages/fx_cast-bin - `fx_cast-bin` — https://aur.archlinux.org/packages/fx_cast-bin
### Daemon Configuration ### Daemon Configuration
@@ -30,10 +29,13 @@ The bridge application is currently supported on Windows, macOS and Linux.
<summary>Daemon configuration (systemd)</summary> <summary>Daemon configuration (systemd)</summary>
1. Create a new `fx_cast` user: 1. Create a new `fx_cast` user:
```sh ```sh
$ sudo useradd --system fx_cast $ sudo useradd --system fx_cast
``` ```
2. Create a service file in `/etc/systemd/system/fx_cast.service`: 2. Create a service file in `/etc/systemd/system/fx_cast.service`:
``` ```
[Unit] [Unit]
Description=fx_cast daemon Description=fx_cast daemon
@@ -46,12 +48,14 @@ Restart=always
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
``` ```
3. Enable the service: 3. Enable the service:
```sh ```sh
$ sudo systemctl enable --now fx_cast $ sudo systemctl enable --now fx_cast
``` ```
</details>
</details>
## Usage ## Usage
@@ -68,36 +72,43 @@ Whitelisted sites should then display a cast button as in Chrome, provided they'
## Building ## Building
### Requirements ### Requirements
* Node.js v16.x.x
* Native build tools (see [here](https://github.com/nodejs/node-gyp#installation)) - Node.js v16.x.x
* Bonjour/Avahi (on Windows/Linux respectively) - Native build tools (see [here](https://github.com/nodejs/node-gyp#installation))
- Bonjour/Avahi (on Windows/Linux respectively)
### Installing dependencies ### Installing dependencies
#### Windows: #### Windows:
* [Bonjour SDK for Windows](https://developer.apple.com/download/more/?=Bonjour%20SDK%20for%20Windows)
* [NSIS](https://nsis.sourceforge.io/Download) - [Bonjour SDK for Windows](https://developer.apple.com/download/more/?=Bonjour%20SDK%20for%20Windows)
- [NSIS](https://nsis.sourceforge.io/Download)
#### Debian / Ubuntu: #### Debian / Ubuntu:
````sh
```sh
$ sudo apt install libavahi-compat-libdnssd-dev dpkg rpm $ sudo apt install libavahi-compat-libdnssd-dev dpkg rpm
```` ```
Runtime packages: `avahi-daemon`. Runtime packages: `avahi-daemon`.
#### Fedora: #### Fedora:
````sh
```sh
$ sudo dnf install avahi-compat-libdns_sd-devel dpkg rpm-build $ sudo dnf install avahi-compat-libdns_sd-devel dpkg rpm-build
```` ```
Runtime packages: `avahi`, `nss-mdns`. Runtime packages: `avahi`, `nss-mdns`.
#### Arch Linux: #### Arch Linux:
````sh
```sh
$ sudo pacman -S avahi dpkg rpm-tools $ sudo pacman -S avahi dpkg rpm-tools
```` ```
### Instructions ### Instructions
````sh ```sh
$ git clone https://github.com/hensm/fx_cast.git $ git clone https://github.com/hensm/fx_cast.git
$ cd fx_cast $ cd fx_cast
$ npm install $ npm install
@@ -108,61 +119,68 @@ $ npm run build
# install. Call `remove-manifest` to restore previous state. # install. Call `remove-manifest` to restore previous state.
$ npm run install-manifest $ npm run install-manifest
$ npm run remove-manifest $ npm run remove-manifest
```` ```
This will build the ext and app, outputting to `dist/`: This will build the ext and app, outputting to `dist/`:
- `dist/app/` - `dist/app/`
... contains the built bridge with launcher script and manifest (with the path pointing that script). The `install-manifest` npm script copies this manifest to the proper location (or adds its current location to the registry on Windows). ... contains the built bridge with launcher script and manifest (with the path pointing that script). The `install-manifest` npm script copies this manifest to the proper location (or adds its current location to the registry on Windows).
- `dist/ext/` - `dist/ext/`
... contains the unpacked extension. ... contains the unpacked extension.
Watching ext changes: Watching ext changes:
````sh ```sh
$ npm run watch:ext $ npm run watch:ext
```` ```
Launch Firefox with built extension (run in separate terminal): Launch Firefox with built extension (run in separate terminal):
````sh ```sh
$ npm run start:ext $ npm run start:ext
```` ```
#### 32-bit on Windows #### 32-bit on Windows
Building a 32-bit version is only supported for Windows. If you're building from a 64-bit system, you'll also need to rebuild any native dependencies as 32-bit. Building a 32-bit version is only supported for Windows. If you're building from a 64-bit system, you'll also need to rebuild any native dependencies as 32-bit.
````sh ```sh
$ npm clean-install --prefix ./app --arch=ia32 # If on a 64-bit system $ npm clean-install --prefix ./app --arch=ia32 # If on a 64-bit system
# If building without packaging # If building without packaging
$ npm run build:app -- -- --arch=x86 --usePkg $ npm run build:app -- -- --arch=x86 --use-pkg
# If packaging # If packaging
$ npm run package:app -- -- --arch=x86 $ npm run package:app -- -- --arch=x86
```` ```
### Build scripts ### Build scripts
Extension build script (`build:ext`) arguments: Extension build script (`build:ext`) arguments:
- `--package` - `--watch`
Should package with web-ext. Rebuild on changes. Incompatible with `--package`.
- `--watch` - `--package`
Should run webpack in watch mode. Package with web-ext.
- `--mirroringAppId` `"<appID>"` - `--mode` `"development"`, `"production"`
Provide an alternative default mirroring receiver app ID. Sets build mode. Defaults to `development` unless packaging.
- `--mode` `"production"`, `"development"`
Run webpack in a different mode. Defaults to `"development"` unless combined with `--package`.
Bridge build script (`build:app`) arguments: Bridge build script (`build:app`) arguments:
- `--usePkg`
Creates a single executable instead of a compiled JavaScript files and a launcher script. - `--package`
- `--package`
Builds and creates installer packages for distribution. Builds and creates installer packages for distribution.
- `--arch` `"x64"`,`"x86"` - `--package-type` `"deb"`, `"rpm"`
Select platform arch to build for. Defaults to current platform arch. Linux installer package type.
- `--use-pkg`
Create single binary with pkg.
- `--arch` `"x64"`, `"x86"`, `"arm64"`
Select platform arch to build for. Defaults to current arch.
| Platform | Supported Architectures |
| --------- | ----------------------- |
| `Windows` | `x86`, `x64` |
| `macOS` | `x64`, `arm64` |
| `Linux` | `x64` |
### Packaging ### Packaging
@@ -172,10 +190,10 @@ Build and package extension and bridge application for current platform:
$ npm run package $ npm run package
``` ```
- `dist/app/` - `dist/app/`
... contains the installer package: `fx_cast_bridge-<version>-<arch>.(pkg|deb|rpm|exe)` ... contains the installer package: `fx_cast_bridge-<version>-<arch>.(pkg|deb|rpm|exe)`
- `dist/ext/` - `dist/ext/`
... contains the built extension archive: `fx_cast-<version>.xpi`. ... contains the built extension archive: `fx_cast-<version>.xpi`.
Packaging examples: Packaging examples:
@@ -184,16 +202,10 @@ $ npm run package:ext # Packaging extension
$ npm run package:app # Packaging bridge application $ npm run package:app # Packaging bridge application
# Linux platforms # Linux platforms
$ npm run package:app -- -- --packageType=deb $ npm run package:app -- -- --package-type=deb
$ npm run package:app -- -- --packageType=rpm $ npm run package:app -- -- --package-type=rpm
``` ```
Bridge package script arguments (includes the build script arguments):
- `--packageType` `"deb"`,`"rpm"`
Select the package type. Defaults to `deb`. Only relevant when building for Linux.
### Testing ### Testing
Testing requires geckodriver (or chromedriver for Chrome parity testing). See [selenium-webdriver](https://www.npmjs.com/package/selenium-webdriver#installation) installation instructions (ignore `npm install`). Testing requires geckodriver (or chromedriver for Chrome parity testing). See [selenium-webdriver](https://www.npmjs.com/package/selenium-webdriver#installation) installation instructions (ignore `npm install`).
@@ -212,24 +224,25 @@ $ npm test
$ SELENIUM_BROWSER=chrome npm test $ SELENIUM_BROWSER=chrome npm test
``` ```
## Video Demos ## Video Demos
These are somewhat outdated now, but show the basic function of the extension: These are somewhat outdated now, but show the basic function of the extension:
[<img width="200" src="https://img.youtube.com/vi/Ex9dWKYguEE/0.jpg" alt="fx_cast Netflix" />](https://www.youtube.com/watch?v=Ex9dWKYguEE) [<img width="200" src="https://img.youtube.com/vi/Ex9dWKYguEE/0.jpg" alt="fx_cast Netflix" />](https://www.youtube.com/watch?v=Ex9dWKYguEE)
[<img width="200" src="https://img.youtube.com/vi/16r8lQKeEX8/0.jpg" alt="fx_cast HTML5" />](https://www.youtube.com/watch?v=16r8lQKeEX8) [<img width="200" src="https://img.youtube.com/vi/16r8lQKeEX8/0.jpg" alt="fx_cast HTML5" />](https://www.youtube.com/watch?v=16r8lQKeEX8)
## Credit ## Credit
- [electron-chromecast](https://github.com/GPMDP/electron-chromecast)[^electron]
- Icons by [icons8](https://icons8.com/):
- `ext/src/ui/options/assets/icons8-cancel-120.png`
- `ext/src/ui/options/assets/icons8-ok-120.png`
- `ext/src/ui/options/assets/icons8-warn-120.png`
- [electron-chromecast](https://github.com/GPMDP/electron-chromecast)[^electron]
- Icons by [icons8](https://icons8.com/):
- `ext/src/ui/options/assets/icons8-cancel-120.png`
- `ext/src/ui/options/assets/icons8-ok-120.png`
- `ext/src/ui/options/assets/icons8-warn-120.png`
## Donations ## Donations
### PayPal ### PayPal
<p style="float: left"> <p style="float: left">
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3Z2FTMSG976WN&source=url"> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3Z2FTMSG976WN&source=url">
<img src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" alt="Donate with PayPal button" align="middle"> <img src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" alt="Donate with PayPal button" align="middle">
@@ -237,9 +250,6 @@ These are somewhat outdated now, but show the basic function of the extension:
<img alt="Donate with PayPal" src="https://i.imgur.com/oisL6Eo.png" align="middle"> <img alt="Donate with PayPal" src="https://i.imgur.com/oisL6Eo.png" align="middle">
</p> </p>
[^arch]: [^arch]: By default, Arch does not configure Avahi to resolve `.local` hostnames via the name service switch (NSS), and the underlying mdns module used by this project relies on [`getaddrinfo`](https://en.wikipedia.org/wiki/Getaddrinfo) to resolve these hostnames correctly.
By default, Arch does not configure Avahi to resolve `.local` hostnames via the name service switch (NSS), and the underlying mdns module used by this project relies on [`getaddrinfo`](https://en.wikipedia.org/wiki/Getaddrinfo) to resolve these hostnames correctly. [^cast_app]: Some sites may only function properly when initiating casting from the in-page player buttons.
[^cast_app]: [^electron]: Since it seems to be causing confusion, this project does not use electron. The electron-chromecast library was only used as a reference for the initial implementation of the API.
Some sites may only function properly when initiating casting from the in-page player buttons.
[^electron]:
Since it seems to be causing confusion, this project does not use electron. The electron-chromecast library was only used as a reference for the initial implementation of the API.

View File

@@ -1,34 +1,44 @@
"use strict"; // @ts-check
const fs = require("fs-extra"); import fs from "fs-extra";
const os = require("os"); import os from "os";
const path = require("path"); import path from "path";
import url from "url";
import { spawnSync } from "child_process";
const minimist = require("minimist"); import mustache from "mustache";
const mustache = require("mustache"); import pkg from "pkg";
const pkg = require("pkg"); import yargs from "yargs";
const { spawnSync } = require("child_process"); import config from "../config.json" assert { type: "json" };
import * as paths from "./lib/paths.js";
const meta = require("../package.json"); const argv = await yargs()
const paths = require("./lib/paths"); .help()
.version(false)
const { author, homepage } = require("../../package.json"); .option("package", {
describe: "Create installer package",
const EXTENSION_ID = "fx_cast@matt.tf"; type: "boolean"
})
// Command line args .option("package-type", {
const argv = minimist(process.argv.slice(2), { describe: "Linux package type",
boolean: ["usePkg", "package"], choices: ["deb", "rpm"],
string: ["arch", "packageType", "nodeVersion"], default: "deb"
default: { })
arch: os.arch(), .option("use-pkg", {
package: false, describe: "Create single binary with pkg",
// Linux package type (deb/rpm) type: "boolean"
packageType: "deb", })
nodeVersion: "16" .option("arch", {
} describe: "Set build architecture",
}); default: os.arch()
})
.option("node-version", {
describe: "Node.js version to target",
default: "16"
})
.conflicts("use-pkg", "package")
.parse(process.argv);
const supportedTargets = { const supportedTargets = {
win32: ["x86", "x64"], win32: ["x86", "x64"],
@@ -45,6 +55,8 @@ if (!supportedTargets[process.platform]?.includes(argv.arch)) {
process.exit(1); process.exit(1);
} }
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
const ROOT_PATH = path.join(__dirname, ".."); const ROOT_PATH = path.join(__dirname, "..");
const BUILD_PATH = path.join(ROOT_PATH, "build"); const BUILD_PATH = path.join(ROOT_PATH, "build");
@@ -57,10 +69,10 @@ const spawnOptions = {
* Shouldn't exist, but cleanup and re-create any existing * Shouldn't exist, but cleanup and re-create any existing
* build directories, just in case. * build directories, just in case.
*/ */
fs.removeSync(BUILD_PATH); fs.rmSync(BUILD_PATH, { force: true, recursive: true });
fs.removeSync(paths.DIST_PATH, { recursive: true }); fs.rmSync(paths.DIST_PATH, { force: true, recursive: true });
fs.ensureDirSync(BUILD_PATH); fs.mkdirSync(BUILD_PATH, { recursive: true });
fs.ensureDirSync(paths.DIST_PATH, { recursive: true }); fs.mkdirSync(paths.DIST_PATH, { recursive: true });
const MDNS_BINDING_PATH = path.join( const MDNS_BINDING_PATH = path.join(
__dirname, __dirname,
@@ -81,10 +93,10 @@ async function build() {
* https://mdn.io/Native_manifests#Native_messaging_manifests * https://mdn.io/Native_manifests#Native_messaging_manifests
*/ */
const manifest = { const manifest = {
name: meta.__applicationName, name: config.applicationName,
description: "", description: "",
type: "stdio", type: "stdio",
allowed_extensions: [EXTENSION_ID] allowed_extensions: [config.extensionId]
}; };
/** /**
@@ -105,7 +117,7 @@ async function build() {
}; };
const executableName = paths.getExecutableName(process.platform); const executableName = paths.getExecutableName(process.platform);
const executablePath = paths.getExecutablePath( const executablePath = paths.getExecutableDirectory(
process.platform, process.platform,
argv.arch argv.arch
); );
@@ -132,7 +144,7 @@ async function build() {
path.join(BUILD_PATH, MDNS_BINDING_NAME) path.join(BUILD_PATH, MDNS_BINDING_NAME)
); );
fs.removeSync(path.join(BUILD_PATH, "src")); fs.rmSync(path.join(BUILD_PATH, "src"));
manifest.path = manifest.path =
!argv.package && argv.usePkg !argv.package && argv.usePkg
@@ -141,7 +153,7 @@ async function build() {
} else { } else {
let launcherPath = path.join( let launcherPath = path.join(
BUILD_PATH, BUILD_PATH,
meta.__applicationExecutableName config.applicationExecutableName
); );
const modulesDir = path.join(ROOT_PATH, "node_modules"); const modulesDir = path.join(ROOT_PATH, "node_modules");
@@ -209,36 +221,42 @@ NODE_PATH="${modulesDir}" node $(dirname $0)/src/main.js --__name $(basename $0)
} }
// Remove build directory // Remove build directory
fs.removeSync(BUILD_PATH); fs.rmSync(BUILD_PATH, { force: true, recursive: true });
} }
/** /**
* Takes a platform and returns the path of the created * Takes a platform and returns the path of the created
* installer package. * installer package.
*
* @param {string} platform
* @param {string} arch
*/ */
async function packageApp(platform, arch) { async function packageApp(platform, arch) {
const packageFunctionArgs = [ /** @type {[ string, string, string, string ]} */
const packageFnArgs = [
arch, arch,
// platformExecutableName paths.getExecutableName(platform),
paths.getExecutableName(platform, arch), paths.getExecutableDirectory(platform, arch),
// platformExecutablePath paths.getManifestDirectory(platform, arch, argv.packageType)
paths.getExecutablePath(platform, arch),
// platformManifestPath
paths.getManifestPath(platform, arch, argv.packageType)
]; ];
switch (platform) { switch (platform) {
case "win32": case "win32":
return packageWin32(...packageFunctionArgs); // Pass without manifest
return packageWin32(
packageFnArgs[0],
packageFnArgs[1],
packageFnArgs[2]
);
case "darwin": case "darwin":
return packageDarwin(...packageFunctionArgs); return packageDarwin(...packageFnArgs);
case "linux": { case "linux": {
switch (argv.packageType) { switch (argv.packageType) {
case "deb": case "deb":
return packageLinuxDeb(...packageFunctionArgs); return packageLinuxDeb(...packageFnArgs);
case "rpm": case "rpm":
return packageLinuxRpm(...packageFunctionArgs); return packageLinuxRpm(...packageFnArgs);
} }
break; break;
@@ -258,52 +276,63 @@ async function packageApp(platform, arch) {
* *
* Requires the pkgbuild and productbuild command line * Requires the pkgbuild and productbuild command line
* utilities. Only possible on macOS. * utilities. Only possible on macOS.
*
* @param {string} arch
* @param {string} platformExecutableName
* @param {string} platformExecutableDirectory
* @param {string} platformManifestDirectory
*/ */
function packageDarwin( function packageDarwin(
arch, arch,
platformExecutableName, platformExecutableName,
platformExecutablePath, platformExecutableDirectory,
platformManifestPath platformManifestDirectory
) { ) {
const outputName = `${meta.__applicationName}-${meta.__applicationVersion}-${arch}.pkg`; const outputName = `${config.applicationName}-${config.applicationVersion}-${arch}.pkg`;
const componentName = `${meta.__applicationName}_component.pkg`; const componentName = `${config.applicationName}_component.pkg`;
const packagingDir = path.join(__dirname, "../packaging/mac/"); const packagingDir = path.join(__dirname, "../packaging/mac/");
const packagingOutputDir = path.join(BUILD_PATH, "packaging"); const packagingOutputDir = path.join(BUILD_PATH, "packaging");
// Create pkgbuild root // Create pkgbuild root
const rootPath = path.join(BUILD_PATH, "root"); const rootPath = path.join(BUILD_PATH, "root");
const rootExecutablePath = path.join(rootPath, platformExecutablePath); const rootExecutableDirectory = path.join(
const rootManifestPath = path.join(rootPath, platformManifestPath); rootPath,
platformExecutableDirectory
);
const rootManifestDirectory = path.join(
rootPath,
platformManifestDirectory
);
// Create install locations // Create install locations
fs.ensureDirSync(rootExecutablePath, { recursive: true }); fs.mkdirSync(rootExecutableDirectory, { recursive: true });
fs.ensureDirSync(rootManifestPath, { recursive: true }); fs.mkdirSync(rootManifestDirectory, { recursive: true });
// Move files to root // Move files to root
fs.moveSync( fs.moveSync(
path.join(BUILD_PATH, platformExecutableName), path.join(BUILD_PATH, platformExecutableName),
path.join(rootExecutablePath, platformExecutableName) path.join(rootExecutableDirectory, platformExecutableName)
); );
fs.moveSync( fs.moveSync(
path.join(BUILD_PATH, MDNS_BINDING_NAME), path.join(BUILD_PATH, MDNS_BINDING_NAME),
path.join(rootExecutablePath, MDNS_BINDING_NAME) path.join(rootExecutableDirectory, MDNS_BINDING_NAME)
); );
fs.moveSync( fs.moveSync(
path.join(BUILD_PATH, paths.MANIFEST_NAME), path.join(BUILD_PATH, paths.MANIFEST_NAME),
path.join(rootManifestPath, paths.MANIFEST_NAME) path.join(rootManifestDirectory, paths.MANIFEST_NAME)
); );
// Copy static files to be processed // Copy static files to be processed
fs.copySync(packagingDir, packagingOutputDir); fs.copySync(packagingDir, packagingOutputDir);
const view = { const view = {
applicationName: meta.__applicationName, applicationName: config.applicationName,
manifestName: paths.MANIFEST_NAME, manifestName: paths.MANIFEST_NAME,
componentName, componentName,
packageId: `tf.matt.${meta.__applicationName}`, packageId: `tf.matt.${config.applicationName}`,
executablePath: platformExecutablePath, executablePath: platformExecutableDirectory,
manifestPath: platformManifestPath manifestPath: platformManifestDirectory
}; };
// Template paths // Template paths
@@ -321,8 +350,8 @@ function packageDarwin(
// Build component package // Build component package
spawnSync( spawnSync(
`pkgbuild --root ${rootPath} \ `pkgbuild --root ${rootPath} \
--identifier "tf.matt.${meta.__applicationName}" \ --identifier "tf.matt.${config.applicationName}" \
--version "${meta.__applicationVersion}" \ --version "${config.applicationVersion}" \
--scripts ${path.join(packagingOutputDir, "scripts")} \ --scripts ${path.join(packagingOutputDir, "scripts")} \
${path.join(BUILD_PATH, componentName)}`, ${path.join(BUILD_PATH, componentName)}`,
spawnOptions spawnOptions
@@ -350,35 +379,46 @@ function packageDarwin(
* (packaging/linux/deb/DEBIAN/control) to root, then builds * (packaging/linux/deb/DEBIAN/control) to root, then builds
* package from root. * package from root.
* Requires the dpkg-deb command line utility. * Requires the dpkg-deb command line utility.
*
* @param {string} arch
* @param {string} platformExecutableName
* @param {string} platformExecutableDirectory
* @param {string} platformManifestDirectory
*/ */
function packageLinuxDeb( function packageLinuxDeb(
arch, arch,
platformExecutableName, platformExecutableName,
platformExecutablePath, platformExecutableDirectory,
platformManifestPath platformManifestDirectory
) { ) {
const outputName = `${meta.__applicationName}-${meta.__applicationVersion}-${arch}.deb`; const outputName = `${config.applicationName}-${config.applicationVersion}-${arch}.deb`;
// Create root // Create root
const rootPath = path.join(BUILD_PATH, "root"); const rootPath = path.join(BUILD_PATH, "root");
const rootExecutablePath = path.join(rootPath, platformExecutablePath); const rootExecutableDirectory = path.join(
const rootManifestPath = path.join(rootPath, platformManifestPath); rootPath,
platformExecutableDirectory
);
const rootManifestDirectory = path.join(
rootPath,
platformManifestDirectory
);
fs.ensureDirSync(rootExecutablePath, { recursive: true }); fs.mkdirSync(rootExecutableDirectory, { recursive: true });
fs.ensureDirSync(rootManifestPath, { recursive: true }); fs.mkdirSync(rootManifestDirectory, { recursive: true });
// Move files to root // Move files to root
fs.moveSync( fs.moveSync(
path.join(BUILD_PATH, platformExecutableName), path.join(BUILD_PATH, platformExecutableName),
path.join(rootExecutablePath, platformExecutableName) path.join(rootExecutableDirectory, platformExecutableName)
); );
fs.moveSync( fs.moveSync(
path.join(BUILD_PATH, MDNS_BINDING_NAME), path.join(BUILD_PATH, MDNS_BINDING_NAME),
path.join(rootExecutablePath, MDNS_BINDING_NAME) path.join(rootExecutableDirectory, MDNS_BINDING_NAME)
); );
fs.moveSync( fs.moveSync(
path.join(BUILD_PATH, paths.MANIFEST_NAME), path.join(BUILD_PATH, paths.MANIFEST_NAME),
path.join(rootManifestPath, paths.MANIFEST_NAME) path.join(rootManifestDirectory, paths.MANIFEST_NAME)
); );
const controlDir = path.join(__dirname, "../packaging/linux/deb/DEBIAN/"); const controlDir = path.join(__dirname, "../packaging/linux/deb/DEBIAN/");
@@ -390,10 +430,10 @@ function packageLinuxDeb(
const view = { const view = {
// Debian package names can't contain underscores // Debian package names can't contain underscores
packageName: meta.__applicationName.replace(/_/g, "-"), packageName: config.applicationName.replace(/_/g, "-"),
applicationName: meta.__applicationName, applicationName: config.applicationName,
applicationVersion: meta.__applicationVersion, applicationVersion: config.applicationVersion,
author author: config.author
}; };
// Do templating on control file // Do templating on control file
@@ -418,14 +458,19 @@ function packageLinuxDeb(
* Templates and uses the spec file * Templates and uses the spec file
* (packaging/linux/rpm/package.spec) to build the package. * (packaging/linux/rpm/package.spec) to build the package.
* Requires the rpmbuild command line utility. * Requires the rpmbuild command line utility.
*
* @param {string} arch
* @param {string} platformExecutableName
* @param {string} platformExecutableDirectory
* @param {string} platformManifestDirectory
*/ */
function packageLinuxRpm( function packageLinuxRpm(
arch, arch,
platformExecutableName, platformExecutableName,
platformExecutablePath, platformExecutableDirectory,
platformManifestPath platformManifestDirectory
) { ) {
const outputName = `${meta.__applicationName}-${meta.__applicationVersion}-${arch}.rpm`; const outputName = `${config.applicationName}-${config.applicationVersion}-${arch}.rpm`;
const specPath = path.join( const specPath = path.join(
__dirname, __dirname,
@@ -435,11 +480,11 @@ function packageLinuxRpm(
const specOutputPath = path.join(BUILD_PATH, path.basename(specPath)); const specOutputPath = path.join(BUILD_PATH, path.basename(specPath));
const view = { const view = {
packageName: meta.__applicationName, packageName: config.applicationName,
applicationName: meta.__applicationName, applicationName: config.applicationName,
applicationVersion: meta.__applicationVersion, applicationVersion: config.applicationVersion,
executablePath: platformExecutablePath, executablePath: platformExecutableDirectory,
manifestPath: platformManifestPath, manifestPath: platformManifestDirectory,
executableName: platformExecutableName, executableName: platformExecutableName,
manifestName: paths.MANIFEST_NAME, manifestName: paths.MANIFEST_NAME,
bindingName: MDNS_BINDING_NAME bindingName: MDNS_BINDING_NAME
@@ -470,18 +515,26 @@ function packageLinuxRpm(
* Uses NSIS to create a GUI installer with an installer * Uses NSIS to create a GUI installer with an installer
* script (packaging/win/installer.nsi). Requires the * script (packaging/win/installer.nsi). Requires the
* makensis command line utility. * makensis command line utility.
*
* @param {string} arch
* @param {string} platformExecutableName
* @param {string} platformExecutableDirectory
*/ */
function packageWin32(arch, platformExecutableName, platformExecutablePath) { function packageWin32(
const outputName = `${meta.__applicationName}-${meta.__applicationVersion}-${arch}.exe`; arch,
platformExecutableName,
platformExecutableDirectory
) {
const outputName = `${config.applicationName}-${config.applicationVersion}-${arch}.exe`;
const scriptPath = path.join(__dirname, "../packaging/win/installer.nsi"); const scriptPath = path.join(__dirname, "../packaging/win/installer.nsi");
const scriptOutputPath = path.join(BUILD_PATH, path.basename(scriptPath)); const scriptOutputPath = path.join(BUILD_PATH, path.basename(scriptPath));
const view = { const view = {
applicationName: meta.__applicationName, applicationName: config.applicationName,
applicationVersion: meta.__applicationVersion, applicationVersion: config.applicationVersion,
executableName: platformExecutableName, executableName: platformExecutableName,
executablePath: platformExecutablePath, executablePath: platformExecutableDirectory,
manifestName: paths.MANIFEST_NAME, manifestName: paths.MANIFEST_NAME,
bindingName: MDNS_BINDING_NAME, bindingName: MDNS_BINDING_NAME,
winRegistryKey: paths.REGISTRY_KEY, winRegistryKey: paths.REGISTRY_KEY,
@@ -489,8 +542,8 @@ function packageWin32(arch, platformExecutableName, platformExecutablePath) {
licensePath: paths.LICENSE_PATH, licensePath: paths.LICENSE_PATH,
// Uninstaller keys // Uninstaller keys
registryPublisher: author, registryPublisher: config.author,
registryUrlInfoAbout: homepage registryUrlInfoAbout: config.homepageUrl
}; };
// Write templated script to build dir // Write templated script to build dir

View File

@@ -1,69 +1,77 @@
const fs = require("fs-extra"); // @ts-check
const os = require("os");
const path = require("path");
const minimist = require("minimist");
const paths = require("./lib/paths"); import fs from "fs-extra";
import os from "os";
import path from "path";
import { spawnSync } from "child_process";
const argv = minimist(process.argv.slice(2), { import yargs from "yargs";
boolean: ["remove"],
default: {
remove: false
}
});
const CURRENT_MANIFEST_PATH = path.join(paths.DIST_PATH, paths.MANIFEST_NAME); import * as paths from "./lib/paths.js";
if (!fs.existsSync(CURRENT_MANIFEST_PATH) && !argv.remove) { const argv = yargs()
console.error("No manifest in dist/app/ to install."); .help()
.version(false)
.option("remove", {
describe: "Uninstall manifest",
type: "boolean"
})
.parseSync(process.argv);
// Path to newly-built manifest
const newManifestPath = path.join(paths.DIST_PATH, paths.MANIFEST_NAME);
if (!fs.existsSync(newManifestPath) && !argv.remove) {
console.error("Error: No manifest to install!");
process.exit(1); process.exit(1);
} }
const platform = os.platform(); console.info(`${argv.remove ? "Uninstalling" : "Installing"} manifest... `);
const arch = os.arch();
const platform = os.platform();
switch (platform) { switch (platform) {
// File-based manifests
case "darwin": case "darwin":
case "linux": { case "linux": {
// Manifest location within home directory // User-specific manifest within home directory
const destination = path.join( const manifestDirectory = path.join(
os.homedir(), os.homedir(),
platform === "linux" platform === "linux"
? ".mozilla/native-messaging-hosts/" ? ".mozilla/native-messaging-hosts"
: paths.getManifestPath(platform, arch) : paths.getManifestDirectory(platform, os.arch())
); );
const manifestPath = path.join(manifestDirectory, paths.MANIFEST_NAME);
if (argv.remove) { if (argv.remove) {
fs.remove(path.join(destination, paths.MANIFEST_NAME)); // Uninstall manifest
break; fs.rmSync(manifestPath);
} else {
// Install manifest
fs.mkdirSync(manifestDirectory, { recursive: true });
fs.copyFileSync(newManifestPath, manifestPath);
} }
// Install manifest
fs.ensureDirSync(destination);
fs.copyFileSync(
CURRENT_MANIFEST_PATH,
path.join(destination, paths.MANIFEST_NAME)
);
break; break;
} }
case "win32": { case "win32": {
const { Registry } = require("rage-edit"); const registryKey = `HKCU\\SOFTWARE\\Mozilla\\NativeMessagingHosts\\${paths.REGISTRY_KEY}`;
const REGISTRY_PATH = `HKCU\\SOFTWARE\\Mozilla\\NativeMessagingHosts\\${paths.REGISTRY_KEY}`;
if (argv.remove) { // Call reg command
Registry.delete(REGISTRY_PATH); spawnSync(
break; argv.remove
} ? `reg delete ${registryKey} /f`
: `reg add ${registryKey} /ve /d "${newManifestPath}" /f`,
Registry.set(REGISTRY_PATH, "", CURRENT_MANIFEST_PATH, "REG_SZ"); {
shell: true,
stdio: [process.stdin, process.stdout, process.stderr]
}
);
break; break;
} }
default: { default:
console.error("Sorry, this installer does not yet support your OS"); console.error("Error: Unsupported platform!");
process.exit(1); process.exit(1);
}
} }

View File

@@ -1,85 +1,98 @@
"use strict"; // @ts-check
const path = require("path"); import path from "path";
import url from "url";
const { import config from "../../config.json" assert { type: "json" };
__applicationName,
__applicationDirectoryName,
__applicationExecutableName
} = require("../../package.json");
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
const rootPath = path.join(__dirname, "../../../"); const rootPath = path.join(__dirname, "../../../");
exports.DIST_PATH = path.join(rootPath, "dist/app"); export const DIST_PATH = path.join(rootPath, "dist/app");
exports.LICENSE_PATH = path.join(rootPath, "LICENSE"); export const LICENSE_PATH = path.join(rootPath, "LICENSE");
exports.REGISTRY_KEY = __applicationName; export const REGISTRY_KEY = config.applicationName;
exports.pkgPlatformMap = { export const pkgPlatformMap = {
win32: "win", win32: "win",
darwin: "macos", darwin: "macos",
linux: "linux" linux: "linux"
}; };
exports.MANIFEST_NAME = `${__applicationName}.json`; export const MANIFEST_NAME = `${config.applicationName}.json`;
exports.getExecutableName = platform => { /**
* @param {string} platform
* @returns {string}
*/
export function getExecutableName(platform) {
switch (platform) { switch (platform) {
case "win32": case "win32":
return `${__applicationExecutableName}.exe`; return `${config.applicationExecutableName}.exe`;
case "darwin": case "darwin":
case "linux": case "linux":
return __applicationExecutableName; return config.applicationExecutableName;
} }
};
exports.getExecutablePath = (platform, arch) => { throw new Error("No executable name for specified platform!");
const EXECUTABLE_PATH_WIN32_X64 = `C:\\Program Files\\${__applicationDirectoryName}\\`; }
const EXECUTABLE_PATH_WIN32_X86 = `C:\\Program Files (x86)\\${__applicationDirectoryName}\\`;
const EXECUTABLE_PATH_DARWIN = `/Library/Application Support/${__applicationDirectoryName}/`; /**
const EXECUTABLE_PATH_LINUX = `/opt/${__applicationDirectoryName}/`; * @param {string} platform
* @param {string} arch
* @returns {string}
*/
export function getExecutableDirectory(platform, arch) {
const EXECUTABLE_DIR_WIN32_X64 = `C:\\Program Files\\${config.applicationDirectoryName}\\`;
const EXECUTABLE_DIR_WIN32_X86 = `C:\\Program Files (x86)\\${config.applicationDirectoryName}\\`;
const EXECUTABLE_DIR_DARWIN = `/Library/Application Support/${config.applicationDirectoryName}/`;
const EXECUTABLE_DIR_LINUX = `/opt/${config.applicationDirectoryName}/`;
switch (platform) { switch (platform) {
case "win32": case "win32":
switch (arch) { switch (arch) {
case "x86": case "x86":
return EXECUTABLE_PATH_WIN32_X86; return EXECUTABLE_DIR_WIN32_X86;
case "x64": case "x64":
return EXECUTABLE_PATH_WIN32_X64; return EXECUTABLE_DIR_WIN32_X64;
} }
break; break;
case "darwin": case "darwin":
return EXECUTABLE_PATH_DARWIN; return EXECUTABLE_DIR_DARWIN;
case "linux": case "linux":
return EXECUTABLE_PATH_LINUX; return EXECUTABLE_DIR_LINUX;
} }
};
exports.getManifestPath = (platform, arch, linuxPackageType) => { throw new Error("No executable directory for specified platform!");
const MANIFEST_PATH_DARWIN = }
/**
* @param {string} platform
* @param {string} arch
* @param {string} [linuxPackageType]
* @returns {string}
*/
export function getManifestDirectory(platform, arch, linuxPackageType) {
const MANIFEST_DIR_DARWIN =
"/Library/Application Support/Mozilla/NativeMessagingHosts/"; "/Library/Application Support/Mozilla/NativeMessagingHosts/";
const MANIFEST_PATH_LINUX_DEB = "/usr/lib/mozilla/native-messaging-hosts/"; const MANIFEST_DIR_LINUX_DEB = "/usr/lib/mozilla/native-messaging-hosts/";
const MANIFEST_PATH_LINUX_RPM = const MANIFEST_DIR_LINUX_RPM = "/usr/lib64/mozilla/native-messaging-hosts/";
"/usr/lib64/mozilla/native-messaging-hosts/";
switch (platform) { switch (platform) {
case "win32": case "win32":
switch (arch) { return getExecutableDirectory(platform, arch);
case "x86":
case "x64":
return exports.getExecutablePath(platform, arch);
}
break;
case "darwin": case "darwin":
return MANIFEST_PATH_DARWIN; return MANIFEST_DIR_DARWIN;
case "linux": case "linux":
switch (linuxPackageType) { switch (linuxPackageType) {
case "deb": case "deb":
return MANIFEST_PATH_LINUX_DEB; return MANIFEST_DIR_LINUX_DEB;
case "rpm": case "rpm":
return MANIFEST_PATH_LINUX_RPM; return MANIFEST_DIR_LINUX_RPM;
} }
break; break;
} }
};
throw new Error("No manifest directory for specified platform!");
}

9
app/config.json Normal file
View File

@@ -0,0 +1,9 @@
{
"author": "Matt Hensman <m@matt.tf>",
"homepageUrl": "https://hensm.github.io/fx_cast",
"applicationName": "fx_cast_bridge",
"applicationVersion": "0.2.0",
"applicationDirectoryName": "fx_cast",
"applicationExecutableName": "fx_cast_bridge",
"extensionId": "fx_cast@matt.tf"
}

292
app/package-lock.json generated
View File

@@ -11,10 +11,10 @@
"fast-srp-hap": "^2.0.4", "fast-srp-hap": "^2.0.4",
"mdns": "^2.7.2", "mdns": "^2.7.2",
"mime-types": "^2.1.35", "mime-types": "^2.1.35",
"minimist": "^1.2.6",
"node-fetch": "^3.2.3", "node-fetch": "^3.2.3",
"tweetnacl": "^1.0.3", "tweetnacl": "^1.0.3",
"ws": "^8.5.0" "ws": "^8.5.0",
"yargs": "^17.5.1"
}, },
"devDependencies": { "devDependencies": {
"@types/mdns": "^0.0.34", "@types/mdns": "^0.0.34",
@@ -23,14 +23,12 @@
"@types/node": "^17.0.26", "@types/node": "^17.0.26",
"@types/node-fetch": "^2.6.1", "@types/node-fetch": "^2.6.1",
"@types/ws": "^8.5.3", "@types/ws": "^8.5.3",
"@types/yargs": "^17.0.11",
"fs-extra": "^10.1.0", "fs-extra": "^10.1.0",
"mustache": "^4.2.0", "mustache": "^4.2.0",
"pkg": "^5.6.0", "pkg": "^5.6.0",
"tiny-typed-emitter": "^2.1.0", "tiny-typed-emitter": "^2.1.0",
"typescript": "^4.6.3" "typescript": "^4.6.3"
},
"optionalDependencies": {
"rage-edit": "^1.2.0"
} }
}, },
"node_modules/@babel/helper-validator-identifier": { "node_modules/@babel/helper-validator-identifier": {
@@ -206,6 +204,21 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/yargs": {
"version": "17.0.11",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.11.tgz",
"integrity": "sha512-aB4y9UDUXTSMxmM4MH+YnuR0g5Cph3FLQBoWoMB21DSvFVAxRVEHEMx3TLh+zUZYMCQtKiqazz0Q4Rre31f/OA==",
"dev": true,
"dependencies": {
"@types/yargs-parser": "*"
}
},
"node_modules/@types/yargs-parser": {
"version": "21.0.0",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
"integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==",
"dev": true
},
"node_modules/agent-base": { "node_modules/agent-base": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -231,7 +244,6 @@
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"dependencies": { "dependencies": {
"color-convert": "^2.0.1" "color-convert": "^2.0.1"
}, },
@@ -430,7 +442,6 @@
"version": "7.0.4", "version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"dependencies": { "dependencies": {
"string-width": "^4.2.0", "string-width": "^4.2.0",
"strip-ansi": "^6.0.0", "strip-ansi": "^6.0.0",
@@ -441,7 +452,6 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -450,7 +460,6 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -459,7 +468,6 @@
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": { "dependencies": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0", "is-fullwidth-code-point": "^3.0.0",
@@ -473,7 +481,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": { "dependencies": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
}, },
@@ -494,7 +501,6 @@
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"dependencies": { "dependencies": {
"color-name": "~1.1.4" "color-name": "~1.1.4"
}, },
@@ -505,8 +511,7 @@
"node_modules/color-name": { "node_modules/color-name": {
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
"dev": true
}, },
"node_modules/combined-stream": { "node_modules/combined-stream": {
"version": "1.0.8", "version": "1.0.8",
@@ -625,8 +630,7 @@
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
"dev": true
}, },
"node_modules/end-of-stream": { "node_modules/end-of-stream": {
"version": "1.4.4", "version": "1.4.4",
@@ -641,7 +645,6 @@
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true,
"engines": { "engines": {
"node": ">=6" "node": ">=6"
} }
@@ -862,7 +865,6 @@
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true,
"engines": { "engines": {
"node": "6.* || 8.* || >= 10.*" "node": "6.* || 8.* || >= 10.*"
} }
@@ -1176,7 +1178,8 @@
"node_modules/minimist": { "node_modules/minimist": {
"version": "1.2.6", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
"dev": true
}, },
"node_modules/mkdirp-classic": { "node_modules/mkdirp-classic": {
"version": "0.5.3", "version": "0.5.3",
@@ -1445,6 +1448,15 @@
"pkg-fetch": "lib-es5/bin.js" "pkg-fetch": "lib-es5/bin.js"
} }
}, },
"node_modules/pkg-fetch/node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/pkg-fetch/node_modules/fs-extra": { "node_modules/pkg-fetch/node_modules/fs-extra": {
"version": "9.1.0", "version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
@@ -1460,6 +1472,15 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/pkg-fetch/node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/pkg-fetch/node_modules/node-fetch": { "node_modules/pkg-fetch/node_modules/node-fetch": {
"version": "2.6.7", "version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@@ -1480,6 +1501,59 @@
} }
} }
}, },
"node_modules/pkg-fetch/node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/pkg-fetch/node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/pkg-fetch/node_modules/yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/pkg-fetch/node_modules/yargs-parser": {
"version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"dev": true,
"engines": {
"node": ">=10"
}
},
"node_modules/pkg/node_modules/fs-extra": { "node_modules/pkg/node_modules/fs-extra": {
"version": "9.1.0", "version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
@@ -1601,12 +1675,6 @@
} }
] ]
}, },
"node_modules/rage-edit": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/rage-edit/-/rage-edit-1.2.0.tgz",
"integrity": "sha512-0RspBRc2s6We4g7hRCvT5mu7YPEnfjvQK8Tt354a2uUNJCMC7MKLvo/1mLvHUCQ/zbP6siQyp5VRZN7UCpMFZg==",
"optional": true
},
"node_modules/rc": { "node_modules/rc": {
"version": "1.2.8", "version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
@@ -1641,7 +1709,6 @@
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
"dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -2048,7 +2115,6 @@
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"dependencies": { "dependencies": {
"ansi-styles": "^4.0.0", "ansi-styles": "^4.0.0",
"string-width": "^4.1.0", "string-width": "^4.1.0",
@@ -2065,7 +2131,6 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -2074,7 +2139,6 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -2083,7 +2147,6 @@
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": { "dependencies": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0", "is-fullwidth-code-point": "^3.0.0",
@@ -2097,7 +2160,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": { "dependencies": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
}, },
@@ -2135,7 +2197,6 @@
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true,
"engines": { "engines": {
"node": ">=10" "node": ">=10"
} }
@@ -2147,37 +2208,34 @@
"dev": true "dev": true
}, },
"node_modules/yargs": { "node_modules/yargs": {
"version": "16.2.0", "version": "17.5.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
"dev": true,
"dependencies": { "dependencies": {
"cliui": "^7.0.2", "cliui": "^7.0.2",
"escalade": "^3.1.1", "escalade": "^3.1.1",
"get-caller-file": "^2.0.5", "get-caller-file": "^2.0.5",
"require-directory": "^2.1.1", "require-directory": "^2.1.1",
"string-width": "^4.2.0", "string-width": "^4.2.3",
"y18n": "^5.0.5", "y18n": "^5.0.5",
"yargs-parser": "^20.2.2" "yargs-parser": "^21.0.0"
}, },
"engines": { "engines": {
"node": ">=10" "node": ">=12"
} }
}, },
"node_modules/yargs-parser": { "node_modules/yargs-parser": {
"version": "20.2.9", "version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true,
"engines": { "engines": {
"node": ">=10" "node": ">=12"
} }
}, },
"node_modules/yargs/node_modules/ansi-regex": { "node_modules/yargs/node_modules/ansi-regex": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -2186,7 +2244,6 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -2195,7 +2252,6 @@
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": { "dependencies": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0", "is-fullwidth-code-point": "^3.0.0",
@@ -2209,7 +2265,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": { "dependencies": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
}, },
@@ -2371,6 +2426,21 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/yargs": {
"version": "17.0.11",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.11.tgz",
"integrity": "sha512-aB4y9UDUXTSMxmM4MH+YnuR0g5Cph3FLQBoWoMB21DSvFVAxRVEHEMx3TLh+zUZYMCQtKiqazz0Q4Rre31f/OA==",
"dev": true,
"requires": {
"@types/yargs-parser": "*"
}
},
"@types/yargs-parser": {
"version": "21.0.0",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
"integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==",
"dev": true
},
"agent-base": { "agent-base": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -2390,7 +2460,6 @@
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": { "requires": {
"color-convert": "^2.0.1" "color-convert": "^2.0.1"
} }
@@ -2533,7 +2602,6 @@
"version": "7.0.4", "version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"requires": { "requires": {
"string-width": "^4.2.0", "string-width": "^4.2.0",
"strip-ansi": "^6.0.0", "strip-ansi": "^6.0.0",
@@ -2543,20 +2611,17 @@
"ansi-regex": { "ansi-regex": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
"dev": true
}, },
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
"dev": true
}, },
"string-width": { "string-width": {
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": { "requires": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0", "is-fullwidth-code-point": "^3.0.0",
@@ -2567,7 +2632,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": { "requires": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
} }
@@ -2584,7 +2648,6 @@
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": { "requires": {
"color-name": "~1.1.4" "color-name": "~1.1.4"
} }
@@ -2592,8 +2655,7 @@
"color-name": { "color-name": {
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
"dev": true
}, },
"combined-stream": { "combined-stream": {
"version": "1.0.8", "version": "1.0.8",
@@ -2680,8 +2742,7 @@
"emoji-regex": { "emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
"dev": true
}, },
"end-of-stream": { "end-of-stream": {
"version": "1.4.4", "version": "1.4.4",
@@ -2695,8 +2756,7 @@
"escalade": { "escalade": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
"dev": true
}, },
"escodegen": { "escodegen": {
"version": "2.0.0", "version": "2.0.0",
@@ -2857,8 +2917,7 @@
"get-caller-file": { "get-caller-file": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
"dev": true
}, },
"github-from-package": { "github-from-package": {
"version": "0.0.0", "version": "0.0.0",
@@ -3086,7 +3145,8 @@
"minimist": { "minimist": {
"version": "1.2.6", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
"dev": true
}, },
"mkdirp-classic": { "mkdirp-classic": {
"version": "0.5.3", "version": "0.5.3",
@@ -3295,6 +3355,12 @@
"yargs": "^16.2.0" "yargs": "^16.2.0"
}, },
"dependencies": { "dependencies": {
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
},
"fs-extra": { "fs-extra": {
"version": "9.1.0", "version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
@@ -3307,6 +3373,12 @@
"universalify": "^2.0.0" "universalify": "^2.0.0"
} }
}, },
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
"node-fetch": { "node-fetch": {
"version": "2.6.7", "version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@@ -3315,6 +3387,47 @@
"requires": { "requires": {
"whatwg-url": "^5.0.0" "whatwg-url": "^5.0.0"
} }
},
"string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
}
},
"strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.1"
}
},
"yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"requires": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
}
},
"yargs-parser": {
"version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"dev": true
} }
} }
}, },
@@ -3393,12 +3506,6 @@
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
"dev": true "dev": true
}, },
"rage-edit": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/rage-edit/-/rage-edit-1.2.0.tgz",
"integrity": "sha512-0RspBRc2s6We4g7hRCvT5mu7YPEnfjvQK8Tt354a2uUNJCMC7MKLvo/1mLvHUCQ/zbP6siQyp5VRZN7UCpMFZg==",
"optional": true
},
"rc": { "rc": {
"version": "1.2.8", "version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
@@ -3429,8 +3536,7 @@
"require-directory": { "require-directory": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
"dev": true
}, },
"resolve": { "resolve": {
"version": "1.22.0", "version": "1.22.0",
@@ -3731,7 +3837,6 @@
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"requires": { "requires": {
"ansi-styles": "^4.0.0", "ansi-styles": "^4.0.0",
"string-width": "^4.1.0", "string-width": "^4.1.0",
@@ -3741,20 +3846,17 @@
"ansi-regex": { "ansi-regex": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
"dev": true
}, },
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
"dev": true
}, },
"string-width": { "string-width": {
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": { "requires": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0", "is-fullwidth-code-point": "^3.0.0",
@@ -3765,7 +3867,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": { "requires": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
} }
@@ -3787,8 +3888,7 @@
"y18n": { "y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
"dev": true
}, },
"yallist": { "yallist": {
"version": "4.0.0", "version": "4.0.0",
@@ -3797,37 +3897,33 @@
"dev": true "dev": true
}, },
"yargs": { "yargs": {
"version": "16.2.0", "version": "17.5.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
"dev": true,
"requires": { "requires": {
"cliui": "^7.0.2", "cliui": "^7.0.2",
"escalade": "^3.1.1", "escalade": "^3.1.1",
"get-caller-file": "^2.0.5", "get-caller-file": "^2.0.5",
"require-directory": "^2.1.1", "require-directory": "^2.1.1",
"string-width": "^4.2.0", "string-width": "^4.2.3",
"y18n": "^5.0.5", "y18n": "^5.0.5",
"yargs-parser": "^20.2.2" "yargs-parser": "^21.0.0"
}, },
"dependencies": { "dependencies": {
"ansi-regex": { "ansi-regex": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
"dev": true
}, },
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
"dev": true
}, },
"string-width": { "string-width": {
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": { "requires": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0", "is-fullwidth-code-point": "^3.0.0",
@@ -3838,7 +3934,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": { "requires": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
} }
@@ -3846,10 +3941,9 @@
} }
}, },
"yargs-parser": { "yargs-parser": {
"version": "20.2.9", "version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="
"dev": true
} }
} }
} }

View File

@@ -1,8 +1,5 @@
{ {
"__applicationName": "fx_cast_bridge", "type": "module",
"__applicationVersion": "0.2.0",
"__applicationDirectoryName": "fx_cast",
"__applicationExecutableName": "fx_cast_bridge",
"scripts": { "scripts": {
"build": "node bin/build.js", "build": "node bin/build.js",
"package": "node bin/build.js --package", "package": "node bin/build.js --package",
@@ -16,10 +13,10 @@
"fast-srp-hap": "^2.0.4", "fast-srp-hap": "^2.0.4",
"mdns": "^2.7.2", "mdns": "^2.7.2",
"mime-types": "^2.1.35", "mime-types": "^2.1.35",
"minimist": "^1.2.6",
"node-fetch": "^3.2.3", "node-fetch": "^3.2.3",
"tweetnacl": "^1.0.3", "tweetnacl": "^1.0.3",
"ws": "^8.5.0" "ws": "^8.5.0",
"yargs": "^17.5.1"
}, },
"devDependencies": { "devDependencies": {
"@types/mdns": "^0.0.34", "@types/mdns": "^0.0.34",
@@ -28,13 +25,11 @@
"@types/node": "^17.0.26", "@types/node": "^17.0.26",
"@types/node-fetch": "^2.6.1", "@types/node-fetch": "^2.6.1",
"@types/ws": "^8.5.3", "@types/ws": "^8.5.3",
"@types/yargs": "^17.0.11",
"fs-extra": "^10.1.0", "fs-extra": "^10.1.0",
"mustache": "^4.2.0", "mustache": "^4.2.0",
"pkg": "^5.6.0", "pkg": "^5.6.0",
"tiny-typed-emitter": "^2.1.0", "tiny-typed-emitter": "^2.1.0",
"typescript": "^4.6.3" "typescript": "^4.6.3"
},
"optionalDependencies": {
"rage-edit": "^1.2.0"
} }
} }

View File

@@ -6,7 +6,7 @@ import { handleCastMessage } from "./components/cast";
import { startDiscovery, stopDiscovery } from "./components/discovery"; import { startDiscovery, stopDiscovery } from "./components/discovery";
import { startMediaServer, stopMediaServer } from "./components/mediaServer"; import { startMediaServer, stopMediaServer } from "./components/mediaServer";
import { __applicationVersion } from "../../package.json"; import { applicationVersion } from "../../config.json";
process.on("SIGTERM", () => { process.on("SIGTERM", () => {
stopDiscovery(); stopDiscovery();
@@ -24,7 +24,7 @@ messaging.on("message", (message: Message) => {
switch (message.subject) { switch (message.subject) {
case "bridge:getInfo": case "bridge:getInfo":
case "bridge:/getInfo": { case "bridge:/getInfo": {
messaging.send(__applicationVersion); messaging.send(applicationVersion);
break; break;
} }

View File

@@ -6,24 +6,28 @@ import WebSocket from "ws";
import { spawn } from "child_process"; import { spawn } from "child_process";
import { Readable } from "stream"; import { Readable } from "stream";
import { DecodeTransform, EncodeTransform } from "./transforms"; import { DecodeTransform, EncodeTransform } from "./transforms.js";
interface DaemonOpts { interface DaemonOpts {
host: string; host: string;
port: number; port: number;
password: string; password?: string;
} }
export function init(opts: DaemonOpts) { export function init(opts: DaemonOpts) {
const server = http.createServer(); const server = http.createServer();
const wss = new WebSocket.Server({ noServer: true }); const wss = new WebSocket.Server({ noServer: true });
process.stdout.write("Starting WebSocket server... "); process.stdout.write(
`Starting WebSocket server at ws://${
opts.host.includes(":") ? `[${opts.host}]` : opts.host
}:${opts.port}... `
);
server.on("listening", () => { server.on("listening", () => {
process.stdout.write("Done!\n"); process.stdout.write("Done!\n");
}); });
wss.on("error", err => { server.on("error", err => {
console.error("Failed!"); console.error("Failed!");
console.error(err.message); console.error(err.message);
}); });

View File

@@ -1,64 +1,55 @@
"use strict"; "use strict";
import path from "path"; import yargs from "yargs";
import minimist from "minimist"; import { applicationName, applicationVersion } from "../config.json";
import { __applicationVersion } from "../package.json";
const argv = minimist(process.argv.slice(2), { const argv = yargs()
boolean: ["daemon", "help", "version"], .scriptName(applicationName)
string: ["__name", "host", "port", "password"], .usage("$0 [args]")
alias: { .help()
d: "daemon", .alias("help", "h")
h: "help", .version(`v${applicationVersion}`)
v: "version", .alias("version", "v")
n: "host", .option("daemon", {
p: "port", alias: "d",
P: "password" describe: `Launch in daemon mode. This starts a WebSocket server that \
}, the extension can be configured to connect to under bridge options.`,
default: { type: "boolean"
__name: path.basename(process.argv[0]), })
daemon: false, .option("host", {
host: "localhost", alias: "n",
port: "9556" describe: `Host for daemon WebSocket server. This must match the host \
} set in the extension options.`,
}); default: "localhost"
})
.option("port", {
alias: "p",
describe: `Port number for daemon WebSocket server. This must match \
the port set in the extension options.`,
default: 9556
})
.option("password", {
alias: "P",
describe: `Set an optional password for the daemon WebSocket server. \
This must match the password set in the extension options.
WARNING: This password is intended only as a basic access control measure and \
is transmitted in plain text even over remote connections!`,
type: "string"
})
.check(argv => {
if (argv.port < 1025 || argv.port > 65535) {
throw new Error("Invalid port specified!");
}
if (argv.version) { return true;
// eslint-disable-next-line no-console })
console.log(`v${__applicationVersion}`); .parseSync(process.argv);
} else if (argv.help) {
// eslint-disable-next-line no-console
console.log(
`Usage: ${argv.__name} [options]
Options:
-h, --help Print usage info
-v, --version Print version info
-d, --daemon Launch in daemon mode. This starts a WebSocket server that
the extension can be configured to connect to under bridge
options.
-n, --host Host for daemon WebSocket server. This must match the host
set in the extension options.
-p, --port Port number for daemon WebSocket server. This must match the
port set in the extension options.
-P, --password Set an optional password for the daemon WebSocket server.
This must match the password set in the extension options.
WARNING: This password is intended only as a basic access
control measure and is transmitted in plain text even over
remote connections!
`
);
} else if (argv.daemon) {
const port = parseInt(argv.port);
if (!port || port < 1025 || port > 65535) {
console.error("Invalid port specified!");
process.exit(1);
}
if (argv.daemon) {
import("./daemon").then(daemon => { import("./daemon").then(daemon => {
daemon.init({ daemon.init({
host: argv.host, host: argv.host,
port, port: argv.port,
password: argv.password password: argv.password
}); });
}); });

View File

@@ -1,10 +1,7 @@
{ {
"extends": "../tsconfig" "extends": "../tsconfig",
, "include": [ "include": ["./src/**/*", "./@types/**/*"],
"./src/**/*" "compilerOptions": {
, "./@types/**/*" "lib": ["ES2020.String", "DOM"]
]
, "compilerOptions": {
"lib": [ "ES2020.String", "DOM" ]
} }
} }

View File

@@ -1,45 +1,50 @@
// @ts-check // @ts-check
"use strict";
const fs = require("fs-extra"); import fs from "fs-extra";
const path = require("path"); import path from "path";
import url from "url";
const esbuild = require("esbuild"); import esbuild from "esbuild";
const minimist = require("minimist"); import sveltePlugin from "esbuild-svelte";
const sveltePlugin = require("esbuild-svelte"); import sveltePreprocess from "svelte-preprocess";
const sveltePreprocess = require("svelte-preprocess"); import yargs from "yargs";
const webExt = require("web-ext"); import webExt from "web-ext";
const { copyFilesPlugin } = require("./lib/copyFilesPlugin.js"); import copyFilesPlugin from "./lib/copyFilesPlugin.js";
const BRIDGE_NAME = "fx_cast_bridge"; const BRIDGE_NAME = "fx_cast_bridge";
const BRIDGE_VERSION = "0.2.0"; const BRIDGE_VERSION = "0.2.0";
const MIRRORING_APP_ID = "19A6F4AE"; const MIRRORING_APP_ID = "19A6F4AE";
const argv = minimist(process.argv.slice(2), { const argv = yargs()
boolean: ["package", "watch"], .help()
string: ["mirroringAppId", "mode"], .version(false)
default: { .option("watch", {
package: false, describe: "Rebuild on changes",
watch: false, type: "boolean"
mirroringAppId: MIRRORING_APP_ID, })
mode: "development" .option("package", {
} describe: "Package with web-ext",
}); type: "boolean",
conflicts: "watch"
if (argv.package && argv.watch) { })
console.error("Cannot package whilst watching files."); .option("mode", {
process.exit(1); describe: "Set build mode",
} choices: ["development", "production"],
default: "development"
})
.parseSync(process.argv);
// If packaging, use production mode // If packaging, use production mode
if (argv.package) { if (argv.package) {
argv.mode = "production"; argv.mode = "production";
} }
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
// Paths // Paths
const rootPath = path.resolve(__dirname, "../"); const rootPath = path.join(__dirname, "../");
const srcPath = path.join(rootPath, "src"); const srcPath = path.join(rootPath, "src");
const distPath = path.join(rootPath, "../dist/ext/"); const distPath = path.join(rootPath, "../dist/ext/");
@@ -75,7 +80,7 @@ const buildOpts = {
define: { define: {
BRIDGE_NAME: `"${BRIDGE_NAME}"`, BRIDGE_NAME: `"${BRIDGE_NAME}"`,
BRIDGE_VERSION: `"${BRIDGE_VERSION}"`, BRIDGE_VERSION: `"${BRIDGE_VERSION}"`,
MIRRORING_APP_ID: `"${argv.mirroringAppId}"` MIRRORING_APP_ID: `"${MIRRORING_APP_ID}"`
}, },
plugins: [ plugins: [
// @ts-ignore // @ts-ignore

View File

@@ -1,11 +1,11 @@
// @ts-check // @ts-check
"use strict"; "use strict";
const path = require("path"); import path from "path";
const fs = require("fs"); import fs from "fs";
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
const esbuild = require("esbuild"); import esbuild from "esbuild";
/** /**
* Walks file tree from a given root path. * Walks file tree from a given root path.
@@ -37,17 +37,14 @@ function* walk(rootPath) {
* *
* @type {(opts: CopyFilesPluginOpts) => esbuild.Plugin} * @type {(opts: CopyFilesPluginOpts) => esbuild.Plugin}
*/ */
exports.copyFilesPlugin = opts => { export default opts => {
if (!fs.existsSync(opts.src)) { if (!fs.existsSync(opts.src)) {
throw new Error("copyFilesPlugin: src path not found!"); throw new Error("copyFilesPlugin: src path not found!");
} }
const matchingPaths = []; const matchingPaths = [...walk(opts.src)].filter(
for (const path of walk(opts.src)) { path => !opts.excludePattern?.test(path)
if (!opts.excludePattern?.test(path)) { );
matchingPaths.push(path);
}
}
return { return {
name: "copy-files", name: "copy-files",

104
ext/package-lock.json generated
View File

@@ -17,7 +17,8 @@
"ts-loader": "^9.2.8", "ts-loader": "^9.2.8",
"typescript": "^4.6.3", "typescript": "^4.6.3",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"web-ext": "^6.8.0" "web-ext": "^6.8.0",
"yargs": "^17.5.1"
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
@@ -753,15 +754,6 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/addons-linter/node_modules/yargs-parser": {
"version": "21.0.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz",
"integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==",
"dev": true,
"engines": {
"node": ">=12"
}
},
"node_modules/addons-moz-compare": { "node_modules/addons-moz-compare": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/addons-moz-compare/-/addons-moz-compare-1.2.0.tgz", "resolved": "https://registry.npmjs.org/addons-moz-compare/-/addons-moz-compare-1.2.0.tgz",
@@ -7433,6 +7425,33 @@
"npm": ">=6.9.0" "npm": ">=6.9.0"
} }
}, },
"node_modules/web-ext/node_modules/yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/web-ext/node_modules/yargs-parser": {
"version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"dev": true,
"engines": {
"node": ">=10"
}
},
"node_modules/webpack": { "node_modules/webpack": {
"version": "5.72.0", "version": "5.72.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.0.tgz", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.0.tgz",
@@ -7690,30 +7709,30 @@
"dev": true "dev": true
}, },
"node_modules/yargs": { "node_modules/yargs": {
"version": "16.2.0", "version": "17.5.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"cliui": "^7.0.2", "cliui": "^7.0.2",
"escalade": "^3.1.1", "escalade": "^3.1.1",
"get-caller-file": "^2.0.5", "get-caller-file": "^2.0.5",
"require-directory": "^2.1.1", "require-directory": "^2.1.1",
"string-width": "^4.2.0", "string-width": "^4.2.3",
"y18n": "^5.0.5", "y18n": "^5.0.5",
"yargs-parser": "^20.2.2" "yargs-parser": "^21.0.0"
}, },
"engines": { "engines": {
"node": ">=10" "node": ">=12"
} }
}, },
"node_modules/yargs-parser": { "node_modules/yargs-parser": {
"version": "20.2.9", "version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=10" "node": ">=12"
} }
}, },
"node_modules/yauzl": { "node_modules/yauzl": {
@@ -8390,12 +8409,6 @@
"y18n": "^5.0.5", "y18n": "^5.0.5",
"yargs-parser": "^21.0.0" "yargs-parser": "^21.0.0"
} }
},
"yargs-parser": {
"version": "21.0.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz",
"integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==",
"dev": true
} }
} }
}, },
@@ -13452,6 +13465,29 @@
"ws": "7.4.6", "ws": "7.4.6",
"yargs": "16.2.0", "yargs": "16.2.0",
"zip-dir": "2.0.0" "zip-dir": "2.0.0"
},
"dependencies": {
"yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"requires": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
}
},
"yargs-parser": {
"version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"dev": true
}
} }
}, },
"webpack": { "webpack": {
@@ -13639,24 +13675,24 @@
"dev": true "dev": true
}, },
"yargs": { "yargs": {
"version": "16.2.0", "version": "17.5.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
"dev": true, "dev": true,
"requires": { "requires": {
"cliui": "^7.0.2", "cliui": "^7.0.2",
"escalade": "^3.1.1", "escalade": "^3.1.1",
"get-caller-file": "^2.0.5", "get-caller-file": "^2.0.5",
"require-directory": "^2.1.1", "require-directory": "^2.1.1",
"string-width": "^4.2.0", "string-width": "^4.2.3",
"y18n": "^5.0.5", "y18n": "^5.0.5",
"yargs-parser": "^20.2.2" "yargs-parser": "^21.0.0"
} }
}, },
"yargs-parser": { "yargs-parser": {
"version": "20.2.9", "version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true "dev": true
}, },
"yauzl": { "yauzl": {

View File

@@ -1,4 +1,5 @@
{ {
"type": "module",
"scripts": { "scripts": {
"build": "node bin/build.js", "build": "node bin/build.js",
"package": "node bin/build.js --package", "package": "node bin/build.js --package",
@@ -19,6 +20,7 @@
"ts-loader": "^9.2.8", "ts-loader": "^9.2.8",
"typescript": "^4.6.3", "typescript": "^4.6.3",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"web-ext": "^6.8.0" "web-ext": "^6.8.0",
"yargs": "^17.5.1"
} }
} }

13
package-lock.json generated
View File

@@ -14,7 +14,6 @@
"fs-extra": "^10.0.1", "fs-extra": "^10.0.1",
"glob": "^7.2.0", "glob": "^7.2.0",
"jasmine-console-reporter": "^3.1.0", "jasmine-console-reporter": "^3.1.0",
"minimist": "^1.2.5",
"prettier": "^2.5.1", "prettier": "^2.5.1",
"prettier-plugin-svelte": "^2.7.0", "prettier-plugin-svelte": "^2.7.0",
"selenium-webdriver": "^4.1.1", "selenium-webdriver": "^4.1.1",
@@ -1374,12 +1373,6 @@
"node": "*" "node": "*"
} }
}, },
"node_modules/minimist": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
"dev": true
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -3056,12 +3049,6 @@
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
}, },
"minimist": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
"dev": true
},
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",

View File

@@ -1,7 +1,4 @@
{ {
"author": "Matt Hensman <m@matt.tf>",
"homepage": "https://hensm.github.io/fx_cast",
"bugs": "https://github.com/hensm/fx_cast",
"scripts": { "scripts": {
"postinstall": "npm run postinstall:app && npm run postinstall:ext", "postinstall": "npm run postinstall:app && npm run postinstall:ext",
"postinstall:app": "cd app && npm install", "postinstall:app": "cd app && npm install",
@@ -30,7 +27,6 @@
"fs-extra": "^10.0.1", "fs-extra": "^10.0.1",
"glob": "^7.2.0", "glob": "^7.2.0",
"jasmine-console-reporter": "^3.1.0", "jasmine-console-reporter": "^3.1.0",
"minimist": "^1.2.5",
"prettier": "^2.5.1", "prettier": "^2.5.1",
"prettier-plugin-svelte": "^2.7.0", "prettier-plugin-svelte": "^2.7.0",
"selenium-webdriver": "^4.1.1", "selenium-webdriver": "^4.1.1",