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.
- **Arch Linux (AUR)**
- `fx_cast` — https://aur.archlinux.org/packages/fx_cast
- `fx_cast-bin` — https://aur.archlinux.org/packages/fx_cast-bin
- **Arch Linux (AUR)**
- `fx_cast` — https://aur.archlinux.org/packages/fx_cast
- `fx_cast-bin` — https://aur.archlinux.org/packages/fx_cast-bin
### Daemon Configuration
@@ -30,10 +29,13 @@ The bridge application is currently supported on Windows, macOS and Linux.
<summary>Daemon configuration (systemd)</summary>
1. Create a new `fx_cast` user:
```sh
$ sudo useradd --system fx_cast
```
2. Create a service file in `/etc/systemd/system/fx_cast.service`:
```
[Unit]
Description=fx_cast daemon
@@ -46,12 +48,14 @@ Restart=always
[Install]
WantedBy=multi-user.target
```
3. Enable the service:
```sh
$ sudo systemctl enable --now fx_cast
```
</details>
</details>
## Usage
@@ -68,36 +72,43 @@ Whitelisted sites should then display a cast button as in Chrome, provided they'
## Building
### Requirements
* Node.js v16.x.x
* Native build tools (see [here](https://github.com/nodejs/node-gyp#installation))
* Bonjour/Avahi (on Windows/Linux respectively)
- Node.js v16.x.x
- Native build tools (see [here](https://github.com/nodejs/node-gyp#installation))
- Bonjour/Avahi (on Windows/Linux respectively)
### Installing dependencies
#### 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:
````sh
```sh
$ sudo apt install libavahi-compat-libdnssd-dev dpkg rpm
````
```
Runtime packages: `avahi-daemon`.
#### Fedora:
````sh
```sh
$ sudo dnf install avahi-compat-libdns_sd-devel dpkg rpm-build
````
```
Runtime packages: `avahi`, `nss-mdns`.
#### Arch Linux:
````sh
```sh
$ sudo pacman -S avahi dpkg rpm-tools
````
```
### Instructions
````sh
```sh
$ git clone https://github.com/hensm/fx_cast.git
$ cd fx_cast
$ npm install
@@ -108,61 +119,68 @@ $ npm run build
# install. Call `remove-manifest` to restore previous state.
$ npm run install-manifest
$ npm run remove-manifest
````
```
This will build the ext and app, outputting to `dist/`:
- `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).
- `dist/ext/`
... contains the unpacked extension.
- `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).
- `dist/ext/`
... contains the unpacked extension.
Watching ext changes:
````sh
```sh
$ npm run watch:ext
````
```
Launch Firefox with built extension (run in separate terminal):
````sh
```sh
$ npm run start:ext
````
```
#### 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.
````sh
```sh
$ npm clean-install --prefix ./app --arch=ia32 # If on a 64-bit system
# If building without packaging
$ npm run build:app -- -- --arch=x86 --usePkg
$ npm run build:app -- -- --arch=x86 --use-pkg
# If packaging
$ npm run package:app -- -- --arch=x86
````
```
### Build scripts
Extension build script (`build:ext`) arguments:
- `--package`
Should package with web-ext.
- `--watch`
Should run webpack in watch mode.
- `--mirroringAppId` `"<appID>"`
Provide an alternative default mirroring receiver app ID.
- `--mode` `"production"`, `"development"`
Run webpack in a different mode. Defaults to `"development"` unless combined with `--package`.
- `--watch`
Rebuild on changes. Incompatible with `--package`.
- `--package`
Package with web-ext.
- `--mode` `"development"`, `"production"`
Sets build mode. Defaults to `development` unless packaging.
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.
- `--arch` `"x64"`,`"x86"`
Select platform arch to build for. Defaults to current platform arch.
- `--package-type` `"deb"`, `"rpm"`
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
@@ -172,10 +190,10 @@ Build and package extension and bridge application for current platform:
$ npm run package
```
- `dist/app/`
... contains the installer package: `fx_cast_bridge-<version>-<arch>.(pkg|deb|rpm|exe)`
- `dist/ext/`
... contains the built extension archive: `fx_cast-<version>.xpi`.
- `dist/app/`
... contains the installer package: `fx_cast_bridge-<version>-<arch>.(pkg|deb|rpm|exe)`
- `dist/ext/`
... contains the built extension archive: `fx_cast-<version>.xpi`.
Packaging examples:
@@ -184,16 +202,10 @@ $ npm run package:ext # Packaging extension
$ npm run package:app # Packaging bridge application
# Linux platforms
$ npm run package:app -- -- --packageType=deb
$ npm run package:app -- -- --packageType=rpm
$ npm run package:app -- -- --package-type=deb
$ 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 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
```
## 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/16r8lQKeEX8/0.jpg" alt="fx_cast HTML5" />](https://www.youtube.com/watch?v=16r8lQKeEX8)
## 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
### PayPal
<p style="float: left">
<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">
@@ -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">
</p>
[^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.
[^cast_app]:
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.
[^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.
[^cast_app]: 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");
const os = require("os");
const path = require("path");
import fs from "fs-extra";
import os from "os";
import path from "path";
import url from "url";
import { spawnSync } from "child_process";
const minimist = require("minimist");
const mustache = require("mustache");
const pkg = require("pkg");
import mustache from "mustache";
import pkg from "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 paths = require("./lib/paths");
const { author, homepage } = require("../../package.json");
const EXTENSION_ID = "fx_cast@matt.tf";
// Command line args
const argv = minimist(process.argv.slice(2), {
boolean: ["usePkg", "package"],
string: ["arch", "packageType", "nodeVersion"],
default: {
arch: os.arch(),
package: false,
// Linux package type (deb/rpm)
packageType: "deb",
nodeVersion: "16"
}
});
const argv = await yargs()
.help()
.version(false)
.option("package", {
describe: "Create installer package",
type: "boolean"
})
.option("package-type", {
describe: "Linux package type",
choices: ["deb", "rpm"],
default: "deb"
})
.option("use-pkg", {
describe: "Create single binary with pkg",
type: "boolean"
})
.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 = {
win32: ["x86", "x64"],
@@ -45,6 +55,8 @@ if (!supportedTargets[process.platform]?.includes(argv.arch)) {
process.exit(1);
}
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
const ROOT_PATH = path.join(__dirname, "..");
const BUILD_PATH = path.join(ROOT_PATH, "build");
@@ -57,10 +69,10 @@ const spawnOptions = {
* Shouldn't exist, but cleanup and re-create any existing
* build directories, just in case.
*/
fs.removeSync(BUILD_PATH);
fs.removeSync(paths.DIST_PATH, { recursive: true });
fs.ensureDirSync(BUILD_PATH);
fs.ensureDirSync(paths.DIST_PATH, { recursive: true });
fs.rmSync(BUILD_PATH, { force: true, recursive: true });
fs.rmSync(paths.DIST_PATH, { force: true, recursive: true });
fs.mkdirSync(BUILD_PATH, { recursive: true });
fs.mkdirSync(paths.DIST_PATH, { recursive: true });
const MDNS_BINDING_PATH = path.join(
__dirname,
@@ -81,10 +93,10 @@ async function build() {
* https://mdn.io/Native_manifests#Native_messaging_manifests
*/
const manifest = {
name: meta.__applicationName,
name: config.applicationName,
description: "",
type: "stdio",
allowed_extensions: [EXTENSION_ID]
allowed_extensions: [config.extensionId]
};
/**
@@ -105,7 +117,7 @@ async function build() {
};
const executableName = paths.getExecutableName(process.platform);
const executablePath = paths.getExecutablePath(
const executablePath = paths.getExecutableDirectory(
process.platform,
argv.arch
);
@@ -132,7 +144,7 @@ async function build() {
path.join(BUILD_PATH, MDNS_BINDING_NAME)
);
fs.removeSync(path.join(BUILD_PATH, "src"));
fs.rmSync(path.join(BUILD_PATH, "src"));
manifest.path =
!argv.package && argv.usePkg
@@ -141,7 +153,7 @@ async function build() {
} else {
let launcherPath = path.join(
BUILD_PATH,
meta.__applicationExecutableName
config.applicationExecutableName
);
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
fs.removeSync(BUILD_PATH);
fs.rmSync(BUILD_PATH, { force: true, recursive: true });
}
/**
* Takes a platform and returns the path of the created
* installer package.
*
* @param {string} platform
* @param {string} arch
*/
async function packageApp(platform, arch) {
const packageFunctionArgs = [
/** @type {[ string, string, string, string ]} */
const packageFnArgs = [
arch,
// platformExecutableName
paths.getExecutableName(platform, arch),
// platformExecutablePath
paths.getExecutablePath(platform, arch),
// platformManifestPath
paths.getManifestPath(platform, arch, argv.packageType)
paths.getExecutableName(platform),
paths.getExecutableDirectory(platform, arch),
paths.getManifestDirectory(platform, arch, argv.packageType)
];
switch (platform) {
case "win32":
return packageWin32(...packageFunctionArgs);
// Pass without manifest
return packageWin32(
packageFnArgs[0],
packageFnArgs[1],
packageFnArgs[2]
);
case "darwin":
return packageDarwin(...packageFunctionArgs);
return packageDarwin(...packageFnArgs);
case "linux": {
switch (argv.packageType) {
case "deb":
return packageLinuxDeb(...packageFunctionArgs);
return packageLinuxDeb(...packageFnArgs);
case "rpm":
return packageLinuxRpm(...packageFunctionArgs);
return packageLinuxRpm(...packageFnArgs);
}
break;
@@ -258,52 +276,63 @@ async function packageApp(platform, arch) {
*
* Requires the pkgbuild and productbuild command line
* utilities. Only possible on macOS.
*
* @param {string} arch
* @param {string} platformExecutableName
* @param {string} platformExecutableDirectory
* @param {string} platformManifestDirectory
*/
function packageDarwin(
arch,
platformExecutableName,
platformExecutablePath,
platformManifestPath
platformExecutableDirectory,
platformManifestDirectory
) {
const outputName = `${meta.__applicationName}-${meta.__applicationVersion}-${arch}.pkg`;
const componentName = `${meta.__applicationName}_component.pkg`;
const outputName = `${config.applicationName}-${config.applicationVersion}-${arch}.pkg`;
const componentName = `${config.applicationName}_component.pkg`;
const packagingDir = path.join(__dirname, "../packaging/mac/");
const packagingOutputDir = path.join(BUILD_PATH, "packaging");
// Create pkgbuild root
const rootPath = path.join(BUILD_PATH, "root");
const rootExecutablePath = path.join(rootPath, platformExecutablePath);
const rootManifestPath = path.join(rootPath, platformManifestPath);
const rootExecutableDirectory = path.join(
rootPath,
platformExecutableDirectory
);
const rootManifestDirectory = path.join(
rootPath,
platformManifestDirectory
);
// Create install locations
fs.ensureDirSync(rootExecutablePath, { recursive: true });
fs.ensureDirSync(rootManifestPath, { recursive: true });
fs.mkdirSync(rootExecutableDirectory, { recursive: true });
fs.mkdirSync(rootManifestDirectory, { recursive: true });
// Move files to root
fs.moveSync(
path.join(BUILD_PATH, platformExecutableName),
path.join(rootExecutablePath, platformExecutableName)
path.join(rootExecutableDirectory, platformExecutableName)
);
fs.moveSync(
path.join(BUILD_PATH, MDNS_BINDING_NAME),
path.join(rootExecutablePath, MDNS_BINDING_NAME)
path.join(rootExecutableDirectory, MDNS_BINDING_NAME)
);
fs.moveSync(
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
fs.copySync(packagingDir, packagingOutputDir);
const view = {
applicationName: meta.__applicationName,
applicationName: config.applicationName,
manifestName: paths.MANIFEST_NAME,
componentName,
packageId: `tf.matt.${meta.__applicationName}`,
executablePath: platformExecutablePath,
manifestPath: platformManifestPath
packageId: `tf.matt.${config.applicationName}`,
executablePath: platformExecutableDirectory,
manifestPath: platformManifestDirectory
};
// Template paths
@@ -321,8 +350,8 @@ function packageDarwin(
// Build component package
spawnSync(
`pkgbuild --root ${rootPath} \
--identifier "tf.matt.${meta.__applicationName}" \
--version "${meta.__applicationVersion}" \
--identifier "tf.matt.${config.applicationName}" \
--version "${config.applicationVersion}" \
--scripts ${path.join(packagingOutputDir, "scripts")} \
${path.join(BUILD_PATH, componentName)}`,
spawnOptions
@@ -350,35 +379,46 @@ function packageDarwin(
* (packaging/linux/deb/DEBIAN/control) to root, then builds
* package from root.
* Requires the dpkg-deb command line utility.
*
* @param {string} arch
* @param {string} platformExecutableName
* @param {string} platformExecutableDirectory
* @param {string} platformManifestDirectory
*/
function packageLinuxDeb(
arch,
platformExecutableName,
platformExecutablePath,
platformManifestPath
platformExecutableDirectory,
platformManifestDirectory
) {
const outputName = `${meta.__applicationName}-${meta.__applicationVersion}-${arch}.deb`;
const outputName = `${config.applicationName}-${config.applicationVersion}-${arch}.deb`;
// Create root
const rootPath = path.join(BUILD_PATH, "root");
const rootExecutablePath = path.join(rootPath, platformExecutablePath);
const rootManifestPath = path.join(rootPath, platformManifestPath);
const rootExecutableDirectory = path.join(
rootPath,
platformExecutableDirectory
);
const rootManifestDirectory = path.join(
rootPath,
platformManifestDirectory
);
fs.ensureDirSync(rootExecutablePath, { recursive: true });
fs.ensureDirSync(rootManifestPath, { recursive: true });
fs.mkdirSync(rootExecutableDirectory, { recursive: true });
fs.mkdirSync(rootManifestDirectory, { recursive: true });
// Move files to root
fs.moveSync(
path.join(BUILD_PATH, platformExecutableName),
path.join(rootExecutablePath, platformExecutableName)
path.join(rootExecutableDirectory, platformExecutableName)
);
fs.moveSync(
path.join(BUILD_PATH, MDNS_BINDING_NAME),
path.join(rootExecutablePath, MDNS_BINDING_NAME)
path.join(rootExecutableDirectory, MDNS_BINDING_NAME)
);
fs.moveSync(
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/");
@@ -390,10 +430,10 @@ function packageLinuxDeb(
const view = {
// Debian package names can't contain underscores
packageName: meta.__applicationName.replace(/_/g, "-"),
applicationName: meta.__applicationName,
applicationVersion: meta.__applicationVersion,
author
packageName: config.applicationName.replace(/_/g, "-"),
applicationName: config.applicationName,
applicationVersion: config.applicationVersion,
author: config.author
};
// Do templating on control file
@@ -418,14 +458,19 @@ function packageLinuxDeb(
* Templates and uses the spec file
* (packaging/linux/rpm/package.spec) to build the package.
* Requires the rpmbuild command line utility.
*
* @param {string} arch
* @param {string} platformExecutableName
* @param {string} platformExecutableDirectory
* @param {string} platformManifestDirectory
*/
function packageLinuxRpm(
arch,
platformExecutableName,
platformExecutablePath,
platformManifestPath
platformExecutableDirectory,
platformManifestDirectory
) {
const outputName = `${meta.__applicationName}-${meta.__applicationVersion}-${arch}.rpm`;
const outputName = `${config.applicationName}-${config.applicationVersion}-${arch}.rpm`;
const specPath = path.join(
__dirname,
@@ -435,11 +480,11 @@ function packageLinuxRpm(
const specOutputPath = path.join(BUILD_PATH, path.basename(specPath));
const view = {
packageName: meta.__applicationName,
applicationName: meta.__applicationName,
applicationVersion: meta.__applicationVersion,
executablePath: platformExecutablePath,
manifestPath: platformManifestPath,
packageName: config.applicationName,
applicationName: config.applicationName,
applicationVersion: config.applicationVersion,
executablePath: platformExecutableDirectory,
manifestPath: platformManifestDirectory,
executableName: platformExecutableName,
manifestName: paths.MANIFEST_NAME,
bindingName: MDNS_BINDING_NAME
@@ -470,18 +515,26 @@ function packageLinuxRpm(
* Uses NSIS to create a GUI installer with an installer
* script (packaging/win/installer.nsi). Requires the
* makensis command line utility.
*
* @param {string} arch
* @param {string} platformExecutableName
* @param {string} platformExecutableDirectory
*/
function packageWin32(arch, platformExecutableName, platformExecutablePath) {
const outputName = `${meta.__applicationName}-${meta.__applicationVersion}-${arch}.exe`;
function packageWin32(
arch,
platformExecutableName,
platformExecutableDirectory
) {
const outputName = `${config.applicationName}-${config.applicationVersion}-${arch}.exe`;
const scriptPath = path.join(__dirname, "../packaging/win/installer.nsi");
const scriptOutputPath = path.join(BUILD_PATH, path.basename(scriptPath));
const view = {
applicationName: meta.__applicationName,
applicationVersion: meta.__applicationVersion,
applicationName: config.applicationName,
applicationVersion: config.applicationVersion,
executableName: platformExecutableName,
executablePath: platformExecutablePath,
executablePath: platformExecutableDirectory,
manifestName: paths.MANIFEST_NAME,
bindingName: MDNS_BINDING_NAME,
winRegistryKey: paths.REGISTRY_KEY,
@@ -489,8 +542,8 @@ function packageWin32(arch, platformExecutableName, platformExecutablePath) {
licensePath: paths.LICENSE_PATH,
// Uninstaller keys
registryPublisher: author,
registryUrlInfoAbout: homepage
registryPublisher: config.author,
registryUrlInfoAbout: config.homepageUrl
};
// Write templated script to build dir

View File

@@ -1,69 +1,77 @@
const fs = require("fs-extra");
const os = require("os");
const path = require("path");
const minimist = require("minimist");
// @ts-check
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), {
boolean: ["remove"],
default: {
remove: false
}
});
import yargs from "yargs";
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) {
console.error("No manifest in dist/app/ to install.");
const argv = yargs()
.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);
}
const platform = os.platform();
const arch = os.arch();
console.info(`${argv.remove ? "Uninstalling" : "Installing"} manifest... `);
const platform = os.platform();
switch (platform) {
// File-based manifests
case "darwin":
case "linux": {
// Manifest location within home directory
const destination = path.join(
// User-specific manifest within home directory
const manifestDirectory = path.join(
os.homedir(),
platform === "linux"
? ".mozilla/native-messaging-hosts/"
: paths.getManifestPath(platform, arch)
? ".mozilla/native-messaging-hosts"
: paths.getManifestDirectory(platform, os.arch())
);
const manifestPath = path.join(manifestDirectory, paths.MANIFEST_NAME);
if (argv.remove) {
fs.remove(path.join(destination, paths.MANIFEST_NAME));
break;
// Uninstall manifest
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;
}
case "win32": {
const { Registry } = require("rage-edit");
const REGISTRY_PATH = `HKCU\\SOFTWARE\\Mozilla\\NativeMessagingHosts\\${paths.REGISTRY_KEY}`;
const registryKey = `HKCU\\SOFTWARE\\Mozilla\\NativeMessagingHosts\\${paths.REGISTRY_KEY}`;
if (argv.remove) {
Registry.delete(REGISTRY_PATH);
break;
}
Registry.set(REGISTRY_PATH, "", CURRENT_MANIFEST_PATH, "REG_SZ");
// Call reg command
spawnSync(
argv.remove
? `reg delete ${registryKey} /f`
: `reg add ${registryKey} /ve /d "${newManifestPath}" /f`,
{
shell: true,
stdio: [process.stdin, process.stdout, process.stderr]
}
);
break;
}
default: {
console.error("Sorry, this installer does not yet support your OS");
default:
console.error("Error: Unsupported platform!");
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 {
__applicationName,
__applicationDirectoryName,
__applicationExecutableName
} = require("../../package.json");
import config from "../../config.json" assert { type: "json" };
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
const rootPath = path.join(__dirname, "../../../");
exports.DIST_PATH = path.join(rootPath, "dist/app");
exports.LICENSE_PATH = path.join(rootPath, "LICENSE");
export const DIST_PATH = path.join(rootPath, "dist/app");
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",
darwin: "macos",
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) {
case "win32":
return `${__applicationExecutableName}.exe`;
return `${config.applicationExecutableName}.exe`;
case "darwin":
case "linux":
return __applicationExecutableName;
return config.applicationExecutableName;
}
};
exports.getExecutablePath = (platform, arch) => {
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}/`;
throw new Error("No executable name for specified platform!");
}
/**
* @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) {
case "win32":
switch (arch) {
case "x86":
return EXECUTABLE_PATH_WIN32_X86;
return EXECUTABLE_DIR_WIN32_X86;
case "x64":
return EXECUTABLE_PATH_WIN32_X64;
return EXECUTABLE_DIR_WIN32_X64;
}
break;
case "darwin":
return EXECUTABLE_PATH_DARWIN;
return EXECUTABLE_DIR_DARWIN;
case "linux":
return EXECUTABLE_PATH_LINUX;
return EXECUTABLE_DIR_LINUX;
}
};
exports.getManifestPath = (platform, arch, linuxPackageType) => {
const MANIFEST_PATH_DARWIN =
throw new Error("No executable directory for specified platform!");
}
/**
* @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/";
const MANIFEST_PATH_LINUX_DEB = "/usr/lib/mozilla/native-messaging-hosts/";
const MANIFEST_PATH_LINUX_RPM =
"/usr/lib64/mozilla/native-messaging-hosts/";
const MANIFEST_DIR_LINUX_DEB = "/usr/lib/mozilla/native-messaging-hosts/";
const MANIFEST_DIR_LINUX_RPM = "/usr/lib64/mozilla/native-messaging-hosts/";
switch (platform) {
case "win32":
switch (arch) {
case "x86":
case "x64":
return exports.getExecutablePath(platform, arch);
}
break;
return getExecutableDirectory(platform, arch);
case "darwin":
return MANIFEST_PATH_DARWIN;
return MANIFEST_DIR_DARWIN;
case "linux":
switch (linuxPackageType) {
case "deb":
return MANIFEST_PATH_LINUX_DEB;
return MANIFEST_DIR_LINUX_DEB;
case "rpm":
return MANIFEST_PATH_LINUX_RPM;
return MANIFEST_DIR_LINUX_RPM;
}
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",
"mdns": "^2.7.2",
"mime-types": "^2.1.35",
"minimist": "^1.2.6",
"node-fetch": "^3.2.3",
"tweetnacl": "^1.0.3",
"ws": "^8.5.0"
"ws": "^8.5.0",
"yargs": "^17.5.1"
},
"devDependencies": {
"@types/mdns": "^0.0.34",
@@ -23,14 +23,12 @@
"@types/node": "^17.0.26",
"@types/node-fetch": "^2.6.1",
"@types/ws": "^8.5.3",
"@types/yargs": "^17.0.11",
"fs-extra": "^10.1.0",
"mustache": "^4.2.0",
"pkg": "^5.6.0",
"tiny-typed-emitter": "^2.1.0",
"typescript": "^4.6.3"
},
"optionalDependencies": {
"rage-edit": "^1.2.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
@@ -206,6 +204,21 @@
"@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": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -231,7 +244,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -430,7 +442,6 @@
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
@@ -441,7 +452,6 @@
"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"
}
@@ -450,7 +460,6 @@
"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"
}
@@ -459,7 +468,6 @@
"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",
@@ -473,7 +481,6 @@
"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"
},
@@ -494,7 +501,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
@@ -505,8 +511,7 @@
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/combined-stream": {
"version": "1.0.8",
@@ -625,8 +630,7 @@
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/end-of-stream": {
"version": "1.4.4",
@@ -641,7 +645,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true,
"engines": {
"node": ">=6"
}
@@ -862,7 +865,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true,
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
@@ -1176,7 +1178,8 @@
"node_modules/minimist": {
"version": "1.2.6",
"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": {
"version": "0.5.3",
@@ -1445,6 +1448,15 @@
"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": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
@@ -1460,6 +1472,15 @@
"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": {
"version": "2.6.7",
"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": {
"version": "9.1.0",
"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": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
@@ -1641,7 +1709,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -2048,7 +2115,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -2065,7 +2131,6 @@
"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"
}
@@ -2074,7 +2139,6 @@
"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"
}
@@ -2083,7 +2147,6 @@
"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",
@@ -2097,7 +2160,6 @@
"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"
},
@@ -2135,7 +2197,6 @@
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true,
"engines": {
"node": ">=10"
}
@@ -2147,37 +2208,34 @@
"dev": true
},
"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,
"version": "17.5.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
"integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
"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",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
"yargs-parser": "^21.0.0"
},
"engines": {
"node": ">=10"
"node": ">=12"
}
},
"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,
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"engines": {
"node": ">=10"
"node": ">=12"
}
},
"node_modules/yargs/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"
}
@@ -2186,7 +2244,6 @@
"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"
}
@@ -2195,7 +2252,6 @@
"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",
@@ -2209,7 +2265,6 @@
"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"
},
@@ -2371,6 +2426,21 @@
"@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": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@@ -2390,7 +2460,6 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
@@ -2533,7 +2602,6 @@
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
@@ -2543,20 +2611,17 @@
"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
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"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
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"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",
@@ -2567,7 +2632,6 @@
"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"
}
@@ -2584,7 +2648,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
@@ -2592,8 +2655,7 @@
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"combined-stream": {
"version": "1.0.8",
@@ -2680,8 +2742,7 @@
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"end-of-stream": {
"version": "1.4.4",
@@ -2695,8 +2756,7 @@
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
},
"escodegen": {
"version": "2.0.0",
@@ -2857,8 +2917,7 @@
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"github-from-package": {
"version": "0.0.0",
@@ -3086,7 +3145,8 @@
"minimist": {
"version": "1.2.6",
"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": {
"version": "0.5.3",
@@ -3295,6 +3355,12 @@
"yargs": "^16.2.0"
},
"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": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
@@ -3307,6 +3373,12 @@
"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": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@@ -3315,6 +3387,47 @@
"requires": {
"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==",
"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": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
@@ -3429,8 +3536,7 @@
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
"dev": true
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
},
"resolve": {
"version": "1.22.0",
@@ -3731,7 +3837,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -3741,20 +3846,17 @@
"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
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"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
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"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",
@@ -3765,7 +3867,6 @@
"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"
}
@@ -3787,8 +3888,7 @@
"y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
},
"yallist": {
"version": "4.0.0",
@@ -3797,37 +3897,33 @@
"dev": true
},
"yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"version": "17.5.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
"integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
"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",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
"yargs-parser": "^21.0.0"
},
"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
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"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
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"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",
@@ -3838,7 +3934,6 @@
"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"
}
@@ -3846,10 +3941,9 @@
}
},
"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
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="
}
}
}

View File

@@ -1,8 +1,5 @@
{
"__applicationName": "fx_cast_bridge",
"__applicationVersion": "0.2.0",
"__applicationDirectoryName": "fx_cast",
"__applicationExecutableName": "fx_cast_bridge",
"type": "module",
"scripts": {
"build": "node bin/build.js",
"package": "node bin/build.js --package",
@@ -16,10 +13,10 @@
"fast-srp-hap": "^2.0.4",
"mdns": "^2.7.2",
"mime-types": "^2.1.35",
"minimist": "^1.2.6",
"node-fetch": "^3.2.3",
"tweetnacl": "^1.0.3",
"ws": "^8.5.0"
"ws": "^8.5.0",
"yargs": "^17.5.1"
},
"devDependencies": {
"@types/mdns": "^0.0.34",
@@ -28,13 +25,11 @@
"@types/node": "^17.0.26",
"@types/node-fetch": "^2.6.1",
"@types/ws": "^8.5.3",
"@types/yargs": "^17.0.11",
"fs-extra": "^10.1.0",
"mustache": "^4.2.0",
"pkg": "^5.6.0",
"tiny-typed-emitter": "^2.1.0",
"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 { startMediaServer, stopMediaServer } from "./components/mediaServer";
import { __applicationVersion } from "../../package.json";
import { applicationVersion } from "../../config.json";
process.on("SIGTERM", () => {
stopDiscovery();
@@ -24,7 +24,7 @@ messaging.on("message", (message: Message) => {
switch (message.subject) {
case "bridge:getInfo":
case "bridge:/getInfo": {
messaging.send(__applicationVersion);
messaging.send(applicationVersion);
break;
}

View File

@@ -6,24 +6,28 @@ import WebSocket from "ws";
import { spawn } from "child_process";
import { Readable } from "stream";
import { DecodeTransform, EncodeTransform } from "./transforms";
import { DecodeTransform, EncodeTransform } from "./transforms.js";
interface DaemonOpts {
host: string;
port: number;
password: string;
password?: string;
}
export function init(opts: DaemonOpts) {
const server = http.createServer();
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", () => {
process.stdout.write("Done!\n");
});
wss.on("error", err => {
server.on("error", err => {
console.error("Failed!");
console.error(err.message);
});

View File

@@ -1,64 +1,55 @@
"use strict";
import path from "path";
import minimist from "minimist";
import { __applicationVersion } from "../package.json";
import yargs from "yargs";
import { applicationName, applicationVersion } from "../config.json";
const argv = minimist(process.argv.slice(2), {
boolean: ["daemon", "help", "version"],
string: ["__name", "host", "port", "password"],
alias: {
d: "daemon",
h: "help",
v: "version",
n: "host",
p: "port",
P: "password"
},
default: {
__name: path.basename(process.argv[0]),
daemon: false,
host: "localhost",
port: "9556"
}
});
const argv = yargs()
.scriptName(applicationName)
.usage("$0 [args]")
.help()
.alias("help", "h")
.version(`v${applicationVersion}`)
.alias("version", "v")
.option("daemon", {
alias: "d",
describe: `Launch in daemon mode. This starts a WebSocket server that \
the extension can be configured to connect to under bridge options.`,
type: "boolean"
})
.option("host", {
alias: "n",
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) {
// eslint-disable-next-line no-console
console.log(`v${__applicationVersion}`);
} 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);
}
return true;
})
.parseSync(process.argv);
if (argv.daemon) {
import("./daemon").then(daemon => {
daemon.init({
host: argv.host,
port,
port: argv.port,
password: argv.password
});
});

View File

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

View File

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

View File

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

104
ext/package-lock.json generated
View File

@@ -17,7 +17,8 @@
"ts-loader": "^9.2.8",
"typescript": "^4.6.3",
"uuid": "^8.3.2",
"web-ext": "^6.8.0"
"web-ext": "^6.8.0",
"yargs": "^17.5.1"
}
},
"node_modules/@babel/code-frame": {
@@ -753,15 +754,6 @@
"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": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/addons-moz-compare/-/addons-moz-compare-1.2.0.tgz",
@@ -7433,6 +7425,33 @@
"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": {
"version": "5.72.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.0.tgz",
@@ -7690,30 +7709,30 @@
"dev": true
},
"node_modules/yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"version": "17.5.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
"integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
"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",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
"yargs-parser": "^21.0.0"
},
"engines": {
"node": ">=10"
"node": ">=12"
}
},
"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==",
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true,
"engines": {
"node": ">=10"
"node": ">=12"
}
},
"node_modules/yauzl": {
@@ -8390,12 +8409,6 @@
"y18n": "^5.0.5",
"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",
"yargs": "16.2.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": {
@@ -13639,24 +13675,24 @@
"dev": true
},
"yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"version": "17.5.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
"integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
"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",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
"yargs-parser": "^21.0.0"
}
},
"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==",
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true
},
"yauzl": {

View File

@@ -1,4 +1,5 @@
{
"type": "module",
"scripts": {
"build": "node bin/build.js",
"package": "node bin/build.js --package",
@@ -19,6 +20,7 @@
"ts-loader": "^9.2.8",
"typescript": "^4.6.3",
"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",
"glob": "^7.2.0",
"jasmine-console-reporter": "^3.1.0",
"minimist": "^1.2.5",
"prettier": "^2.5.1",
"prettier-plugin-svelte": "^2.7.0",
"selenium-webdriver": "^4.1.1",
@@ -1374,12 +1373,6 @@
"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": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -3056,12 +3049,6 @@
"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": {
"version": "2.1.2",
"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": {
"postinstall": "npm run postinstall:app && npm run postinstall:ext",
"postinstall:app": "cd app && npm install",
@@ -30,7 +27,6 @@
"fs-extra": "^10.0.1",
"glob": "^7.2.0",
"jasmine-console-reporter": "^3.1.0",
"minimist": "^1.2.5",
"prettier": "^2.5.1",
"prettier-plugin-svelte": "^2.7.0",
"selenium-webdriver": "^4.1.1",