Nativefier/src/cli.ts

700 lines
22 KiB
TypeScript
Raw Normal View History

Revamp and move to TypeScript (#898) ## Breaking changes - Require **Node >= 8.10.0 and npm 5.6.0** - Move to **Electron 8.1.1**. - That's it. Lots of care went into breaking CLI & programmatic behavior as little as possible. **Please report regressions**. - Known issue: build may fail behind a proxy. Get in touch if you use one: https://github.com/jiahaog/nativefier/issues/907#issuecomment-596144768 ## Changes summary Nativefier didn't get much love recently, to the point that it's becoming hard to run on recent Node, due to old dependencies. Also, some past practices now seem weird, as better expressible by modern JS/TS, discouraging contributions including mine. Addressing this, and one thing leading to another, came a bigger-than-expected revamp, aiming at making Nativefier more **lean, stable, future-proof, user-friendly and dev-friendly**, while **not changing the CLI/programmatic interfaces**. Highlights: - **Require Node>=8**, as imposed by many of our dependencies. Node 8 is twice LTS, and easily available even in conservative Linux distros. No reason not to demand it. - **Default to Electron 8**. - **Bump** all dependencies to latest version, including electron-packager. - **Move to TS**. TS is great. As of today, I see no reason not to use it, and fight interface bugs at runtime rather than at compile time. With that, get rid of everything Babel/Webpack. - **Move away from Gulp**. Gulp's selling point is perf via streaming, but for small builds like Nativefier, npm tasks are plenty good and less dependency bloat. Gulp was the driver for this PR: broken on Node 12, and I didn't feel like just upgrading and keeping it. - Add tons of **verbose logs** everywhere it makes sense, to have a fine & clear trace of the program flow. This will be helpful to debug user-reported issues, and already helped me fix a few bugs. - With better simple logging, get rid of the quirky and buggy progress bar based on package `progress`. Nice logging (minimal by default, the verbose logging mentioned above is only used when passing `--verbose`) is better and one less dependency. - **Dump `async` package**, a relic from old callback-hell early Node. Also dump a few other micro-packages unnecessary now. - A first pass of code **cleanup** thanks to modern JS/TS features: fixes, simplifications, jsdoc type annotations to types, etc. - **Remove GitHub integrations Hound & CodeClimate**, which are more exotic than good'ol'linters, and whose signal-to-noise ratio is too low. - Quality: **Add tests** and add **Windows + macOS CI builds**. Also, add a **manual test script**, helping to quickly verify the hard-to-programatically-test stuff before releases, and limit regressions. - **Fix a very small number of existing bugs**. The goal of this PR was *not* to fix bugs, but to get Nativefier in better shape to do so. Bugfixes will come later. Still, these got addressed: - Add common `Alt`+`Left`/`Right` for previous/next navigation. - Improve #379: fix zoom with `Ctrl` + numpad `+`/`-` - Fix pinch-to-zoom (see https://github.com/jiahaog/nativefier/issues/379#issuecomment-598612128 )
2020-03-15 21:50:01 +01:00
#!/usr/bin/env node
2016-01-24 14:07:22 +01:00
import 'source-map-support/register';
import electronPackager = require('electron-packager');
Revamp and move to TypeScript (#898) ## Breaking changes - Require **Node >= 8.10.0 and npm 5.6.0** - Move to **Electron 8.1.1**. - That's it. Lots of care went into breaking CLI & programmatic behavior as little as possible. **Please report regressions**. - Known issue: build may fail behind a proxy. Get in touch if you use one: https://github.com/jiahaog/nativefier/issues/907#issuecomment-596144768 ## Changes summary Nativefier didn't get much love recently, to the point that it's becoming hard to run on recent Node, due to old dependencies. Also, some past practices now seem weird, as better expressible by modern JS/TS, discouraging contributions including mine. Addressing this, and one thing leading to another, came a bigger-than-expected revamp, aiming at making Nativefier more **lean, stable, future-proof, user-friendly and dev-friendly**, while **not changing the CLI/programmatic interfaces**. Highlights: - **Require Node>=8**, as imposed by many of our dependencies. Node 8 is twice LTS, and easily available even in conservative Linux distros. No reason not to demand it. - **Default to Electron 8**. - **Bump** all dependencies to latest version, including electron-packager. - **Move to TS**. TS is great. As of today, I see no reason not to use it, and fight interface bugs at runtime rather than at compile time. With that, get rid of everything Babel/Webpack. - **Move away from Gulp**. Gulp's selling point is perf via streaming, but for small builds like Nativefier, npm tasks are plenty good and less dependency bloat. Gulp was the driver for this PR: broken on Node 12, and I didn't feel like just upgrading and keeping it. - Add tons of **verbose logs** everywhere it makes sense, to have a fine & clear trace of the program flow. This will be helpful to debug user-reported issues, and already helped me fix a few bugs. - With better simple logging, get rid of the quirky and buggy progress bar based on package `progress`. Nice logging (minimal by default, the verbose logging mentioned above is only used when passing `--verbose`) is better and one less dependency. - **Dump `async` package**, a relic from old callback-hell early Node. Also dump a few other micro-packages unnecessary now. - A first pass of code **cleanup** thanks to modern JS/TS features: fixes, simplifications, jsdoc type annotations to types, etc. - **Remove GitHub integrations Hound & CodeClimate**, which are more exotic than good'ol'linters, and whose signal-to-noise ratio is too low. - Quality: **Add tests** and add **Windows + macOS CI builds**. Also, add a **manual test script**, helping to quickly verify the hard-to-programatically-test stuff before releases, and limit regressions. - **Fix a very small number of existing bugs**. The goal of this PR was *not* to fix bugs, but to get Nativefier in better shape to do so. Bugfixes will come later. Still, these got addressed: - Add common `Alt`+`Left`/`Right` for previous/next navigation. - Improve #379: fix zoom with `Ctrl` + numpad `+`/`-` - Fix pinch-to-zoom (see https://github.com/jiahaog/nativefier/issues/379#issuecomment-598612128 )
2020-03-15 21:50:01 +01:00
import * as log from 'loglevel';
import yargs from 'yargs';
Revamp and move to TypeScript (#898) ## Breaking changes - Require **Node >= 8.10.0 and npm 5.6.0** - Move to **Electron 8.1.1**. - That's it. Lots of care went into breaking CLI & programmatic behavior as little as possible. **Please report regressions**. - Known issue: build may fail behind a proxy. Get in touch if you use one: https://github.com/jiahaog/nativefier/issues/907#issuecomment-596144768 ## Changes summary Nativefier didn't get much love recently, to the point that it's becoming hard to run on recent Node, due to old dependencies. Also, some past practices now seem weird, as better expressible by modern JS/TS, discouraging contributions including mine. Addressing this, and one thing leading to another, came a bigger-than-expected revamp, aiming at making Nativefier more **lean, stable, future-proof, user-friendly and dev-friendly**, while **not changing the CLI/programmatic interfaces**. Highlights: - **Require Node>=8**, as imposed by many of our dependencies. Node 8 is twice LTS, and easily available even in conservative Linux distros. No reason not to demand it. - **Default to Electron 8**. - **Bump** all dependencies to latest version, including electron-packager. - **Move to TS**. TS is great. As of today, I see no reason not to use it, and fight interface bugs at runtime rather than at compile time. With that, get rid of everything Babel/Webpack. - **Move away from Gulp**. Gulp's selling point is perf via streaming, but for small builds like Nativefier, npm tasks are plenty good and less dependency bloat. Gulp was the driver for this PR: broken on Node 12, and I didn't feel like just upgrading and keeping it. - Add tons of **verbose logs** everywhere it makes sense, to have a fine & clear trace of the program flow. This will be helpful to debug user-reported issues, and already helped me fix a few bugs. - With better simple logging, get rid of the quirky and buggy progress bar based on package `progress`. Nice logging (minimal by default, the verbose logging mentioned above is only used when passing `--verbose`) is better and one less dependency. - **Dump `async` package**, a relic from old callback-hell early Node. Also dump a few other micro-packages unnecessary now. - A first pass of code **cleanup** thanks to modern JS/TS features: fixes, simplifications, jsdoc type annotations to types, etc. - **Remove GitHub integrations Hound & CodeClimate**, which are more exotic than good'ol'linters, and whose signal-to-noise ratio is too low. - Quality: **Add tests** and add **Windows + macOS CI builds**. Also, add a **manual test script**, helping to quickly verify the hard-to-programatically-test stuff before releases, and limit regressions. - **Fix a very small number of existing bugs**. The goal of this PR was *not* to fix bugs, but to get Nativefier in better shape to do so. Bugfixes will come later. Still, these got addressed: - Add common `Alt`+`Left`/`Right` for previous/next navigation. - Improve #379: fix zoom with `Ctrl` + numpad `+`/`-` - Fix pinch-to-zoom (see https://github.com/jiahaog/nativefier/issues/379#issuecomment-598612128 )
2020-03-15 21:50:01 +01:00
import { DEFAULT_ELECTRON_VERSION } from './constants';
import {
camelCased,
checkInternet,
getProcessEnvs,
isArgFormatInvalid,
} from './helpers/helpers';
import { supportedArchs, supportedPlatforms } from './infer/inferOs';
Revamp and move to TypeScript (#898) ## Breaking changes - Require **Node >= 8.10.0 and npm 5.6.0** - Move to **Electron 8.1.1**. - That's it. Lots of care went into breaking CLI & programmatic behavior as little as possible. **Please report regressions**. - Known issue: build may fail behind a proxy. Get in touch if you use one: https://github.com/jiahaog/nativefier/issues/907#issuecomment-596144768 ## Changes summary Nativefier didn't get much love recently, to the point that it's becoming hard to run on recent Node, due to old dependencies. Also, some past practices now seem weird, as better expressible by modern JS/TS, discouraging contributions including mine. Addressing this, and one thing leading to another, came a bigger-than-expected revamp, aiming at making Nativefier more **lean, stable, future-proof, user-friendly and dev-friendly**, while **not changing the CLI/programmatic interfaces**. Highlights: - **Require Node>=8**, as imposed by many of our dependencies. Node 8 is twice LTS, and easily available even in conservative Linux distros. No reason not to demand it. - **Default to Electron 8**. - **Bump** all dependencies to latest version, including electron-packager. - **Move to TS**. TS is great. As of today, I see no reason not to use it, and fight interface bugs at runtime rather than at compile time. With that, get rid of everything Babel/Webpack. - **Move away from Gulp**. Gulp's selling point is perf via streaming, but for small builds like Nativefier, npm tasks are plenty good and less dependency bloat. Gulp was the driver for this PR: broken on Node 12, and I didn't feel like just upgrading and keeping it. - Add tons of **verbose logs** everywhere it makes sense, to have a fine & clear trace of the program flow. This will be helpful to debug user-reported issues, and already helped me fix a few bugs. - With better simple logging, get rid of the quirky and buggy progress bar based on package `progress`. Nice logging (minimal by default, the verbose logging mentioned above is only used when passing `--verbose`) is better and one less dependency. - **Dump `async` package**, a relic from old callback-hell early Node. Also dump a few other micro-packages unnecessary now. - A first pass of code **cleanup** thanks to modern JS/TS features: fixes, simplifications, jsdoc type annotations to types, etc. - **Remove GitHub integrations Hound & CodeClimate**, which are more exotic than good'ol'linters, and whose signal-to-noise ratio is too low. - Quality: **Add tests** and add **Windows + macOS CI builds**. Also, add a **manual test script**, helping to quickly verify the hard-to-programatically-test stuff before releases, and limit regressions. - **Fix a very small number of existing bugs**. The goal of this PR was *not* to fix bugs, but to get Nativefier in better shape to do so. Bugfixes will come later. Still, these got addressed: - Add common `Alt`+`Left`/`Right` for previous/next navigation. - Improve #379: fix zoom with `Ctrl` + numpad `+`/`-` - Fix pinch-to-zoom (see https://github.com/jiahaog/nativefier/issues/379#issuecomment-598612128 )
2020-03-15 21:50:01 +01:00
import { buildNativefierApp } from './main';
import { RawOptions } from '../shared/src/options/model';
import { parseJson } from './utils/parseUtils';
import { buildUniversalApp } from './build/buildNativefierApp';
export function initArgs(argv: string[]): yargs.Argv<RawOptions> {
const sanitizedArgs = sanitizeArgs(argv);
const args = yargs(sanitizedArgs)
.scriptName('nativefier')
.usage(
'$0 <targetUrl> [outputDirectory] [other options]\nor\n$0 --upgrade <pathToExistingApp> [other options]',
)
.example(
'$0 <targetUrl> -n <name>',
'Make an app from <targetUrl> and set the application name to <name>',
)
.example(
'$0 --upgrade <pathToExistingApp>',
'Upgrade (in place) the existing Nativefier app at <pathToExistingApp>',
)
.example(
'$0 <targetUrl> -p <platform> -a <arch>',
'Make an app from <targetUrl> for the OS <platform> and CPU architecture <arch>',
)
.example(
'for more examples and help...',
'See https://github.com/nativefier/nativefier/blob/master/CATALOG.md',
)
.positional('targetUrl', {
description:
'the URL that you wish to to turn into a native app; required if not using --upgrade',
type: 'string',
})
.positional('outputDirectory', {
defaultDescription:
'defaults to the current directory, or env. var. NATIVEFIER_APPS_DIR if set',
description: 'the directory to generate the app in',
normalize: true,
type: 'string',
})
// App Creation Options
.option('a', {
alias: 'arch',
choices: supportedArchs,
defaultDescription: "current Node's arch",
description: 'the CPU architecture to build for',
type: 'string',
})
.option('c', {
alias: 'conceal',
default: false,
description: 'package the app source code into an asar archive',
type: 'boolean',
})
.option('e', {
alias: 'electron-version',
defaultDescription: DEFAULT_ELECTRON_VERSION,
description:
"specify the electron version to use (without the 'v'); see https://github.com/electron/electron/releases",
})
.option('global-shortcuts', {
description:
'define global keyboard shortcuts via a JSON file; See https://github.com/nativefier/nativefier/blob/master/API.md#global-shortcuts',
normalize: true,
type: 'string',
})
.option('i', {
alias: 'icon',
description:
'the icon file to use as the icon for the app (.ico on Windows, .icns/.png on macOS, .png on Linux)',
normalize: true,
type: 'string',
})
.option('n', {
alias: 'name',
defaultDescription: 'the title of the page passed via targetUrl',
description: 'specify the name of the app',
type: 'string',
})
.option('no-overwrite', {
default: false,
description: 'do not overwrite output directory if it already exists',
type: 'boolean',
})
.option('overwrite', {
// This is needed to have the `no-overwrite` flag to work correctly
default: true,
hidden: true,
type: 'boolean',
})
.option('p', {
alias: 'platform',
choices: supportedPlatforms,
defaultDescription: 'current operating system',
description: 'the operating system platform to build for',
type: 'string',
})
.option('portable', {
default: false,
description:
'make the app store its user data in the app folder; WARNING: see https://github.com/nativefier/nativefier/blob/master/API.md#portable for security risks',
type: 'boolean',
})
.option('upgrade', {
description:
'upgrade an app built by an older version of Nativefier\nYou must pass the full path to the existing app executable (app will be overwritten with upgraded version by default)',
normalize: true,
type: 'string',
})
.option('widevine', {
default: false,
description:
"use a Widevine-enabled version of Electron for DRM playback (use at your own risk, it's unofficial, provided by CastLabs)",
type: 'boolean',
})
.group(
[
'arch',
'conceal',
'electron-version',
'global-shortcuts',
'icon',
'name',
'no-overwrite',
'platform',
'portable',
'upgrade',
'widevine',
],
decorateYargOptionGroup('App Creation Options'),
)
// App Window Options
.option('always-on-top', {
default: false,
description: 'enable always on top window',
type: 'boolean',
})
.option('background-color', {
description:
"set the app background color, for better integration while the app is loading. Example value: '#2e2c29'",
type: 'string',
})
.option('bookmarks-menu', {
description:
'create a bookmarks menu (via JSON file); See https://github.com/nativefier/nativefier/blob/master/API.md#bookmarks-menu',
normalize: true,
type: 'string',
})
.option('browserwindow-options', {
coerce: parseJson,
description:
'override Electron BrowserWindow options (via JSON string); see https://github.com/nativefier/nativefier/blob/master/API.md#browserwindow-options',
})
.option('disable-context-menu', {
default: false,
description: 'disable the context menu (right click)',
type: 'boolean',
})
.option('disable-dev-tools', {
default: false,
description: 'disable developer tools (Ctrl+Shift+I / F12)',
type: 'boolean',
})
.option('full-screen', {
default: false,
description: 'always start the app full screen',
type: 'boolean',
})
.option('height', {
defaultDescription: '800',
description: 'set window default height in pixels',
type: 'number',
})
.option('hide-window-frame', {
default: false,
description: 'disable window frame and controls',
type: 'boolean',
})
.option('m', {
alias: 'show-menu-bar',
default: false,
description: 'set menu bar visible',
type: 'boolean',
})
.option('max-height', {
defaultDescription: 'unlimited',
description: 'set window maximum height in pixels',
type: 'number',
})
.option('max-width', {
defaultDescription: 'unlimited',
description: 'set window maximum width in pixels',
type: 'number',
})
.option('maximize', {
default: false,
description: 'always start the app maximized',
type: 'boolean',
})
.option('min-height', {
defaultDescription: '0',
description: 'set window minimum height in pixels',
type: 'number',
})
.option('min-width', {
defaultDescription: '0',
description: 'set window minimum width in pixels',
type: 'number',
})
.option('process-envs', {
coerce: getProcessEnvs,
description:
'a JSON string of key/value pairs to be set as environment variables before any browser windows are opened',
})
.option('single-instance', {
default: false,
description: 'allow only a single instance of the app',
type: 'boolean',
})
.option('tray', {
default: 'false',
description:
"allow app to stay in system tray. If 'start-in-tray' is set as argument, don't show main window on first start",
choices: ['true', 'false', 'start-in-tray'],
})
.option('width', {
defaultDescription: '1280',
description: 'app window default width in pixels',
type: 'number',
})
.option('x', {
description: 'set window x location in pixels from left',
type: 'number',
})
.option('y', {
description: 'set window y location in pixels from top',
type: 'number',
})
.option('zoom', {
default: 1.0,
description: 'set the default zoom factor for the app',
type: 'number',
})
.group(
[
'always-on-top',
'background-color',
'bookmarks-menu',
'browserwindow-options',
'disable-context-menu',
'disable-dev-tools',
'full-screen',
'height',
'hide-window-frame',
'm',
'max-width',
'max-height',
'maximize',
'min-height',
'min-width',
'process-envs',
'single-instance',
'tray',
'width',
'x',
'y',
'zoom',
],
decorateYargOptionGroup('App Window Options'),
)
// Internal Browser Options
.option('file-download-options', {
coerce: parseJson,
description:
'a JSON string defining file download options; see https://github.com/sindresorhus/electron-dl',
})
.option('inject', {
description:
'path to a CSS/JS file to be injected; pass multiple times to inject multiple files',
string: true,
type: 'array',
})
.option('lang', {
defaultDescription: 'os language at runtime of the app',
description:
'set the language or locale to render the web site as (e.g., "fr", "en-US", "es", etc.)',
type: 'string',
})
.option('u', {
alias: 'user-agent',
description:
"set the app's user agent string; may also use 'edge', 'firefox', or 'safari' to have one auto-generated",
type: 'string',
})
.option('user-agent-honest', {
alias: 'honest',
default: false,
description:
'prevent the normal changing of the user agent string to appear as a regular Chrome browser',
type: 'boolean',
})
.group(
[
'file-download-options',
'inject',
'lang',
'user-agent',
'user-agent-honest',
],
decorateYargOptionGroup('Internal Browser Options'),
)
// Internal Browser Cache Options
.option('clear-cache', {
default: false,
description: 'prevent the app from preserving cache between launches',
type: 'boolean',
})
.option('disk-cache-size', {
defaultDescription: 'chromium default',
description:
'set the maximum disk space (in bytes) to be used by the disk cache',
type: 'number',
})
.group(
['clear-cache', 'disk-cache-size'],
decorateYargOptionGroup('Internal Browser Cache Options'),
)
// URL Handling Options
.option('block-external-urls', {
default: false,
description: `forbid navigation to URLs not considered "internal" (see '--internal-urls'). Instead of opening in an external browser, attempts to navigate to external URLs will be blocked`,
type: 'boolean',
})
.option('internal-urls', {
defaultDescription: 'URLs sharing the same base domain',
2022-02-06 23:49:30 +01:00
description: `regex of URLs to consider "internal"; by default matches based on domain (see '--strict-internal-urls'); all other URLs will be opened in an external browser`,
type: 'string',
})
.option('strict-internal-urls', {
default: false,
2022-02-06 23:49:30 +01:00
description: 'disable domain-based matching on internal URLs',
type: 'boolean',
})
.option('proxy-rules', {
description:
'proxy rules; see https://www.electronjs.org/docs/api/session#sessetproxyconfig',
type: 'string',
})
.group(
2022-02-06 23:49:30 +01:00
[
'block-external-urls',
'internal-urls',
'strict-internal-urls',
'proxy-rules',
],
decorateYargOptionGroup('URL Handling Options'),
)
// Auth Options
.option('basic-auth-password', {
description: 'basic http(s) auth password',
type: 'string',
})
.option('basic-auth-username', {
description: 'basic http(s) auth username',
type: 'string',
})
.group(
['basic-auth-password', 'basic-auth-username'],
decorateYargOptionGroup('Auth Options'),
)
// Graphics Options
.option('disable-gpu', {
default: false,
description: 'disable hardware acceleration',
type: 'boolean',
})
.option('enable-es3-apis', {
default: false,
description: 'force activation of WebGL 2.0',
type: 'boolean',
})
.option('ignore-gpu-blacklist', {
default: false,
description: 'force WebGL apps to work on unsupported GPUs',
type: 'boolean',
})
.group(
['disable-gpu', 'enable-es3-apis', 'ignore-gpu-blacklist'],
decorateYargOptionGroup('Graphics Options'),
)
// (In)Security Options
.option('disable-old-build-warning-yesiknowitisinsecure', {
default: false,
description:
'disable warning shown when opening an app made too long ago; Nativefier uses the Chrome browser (through Electron), and it is dangerous to keep using an old version of it',
type: 'boolean',
})
.option('ignore-certificate', {
default: false,
description: 'ignore certificate-related errors',
type: 'boolean',
})
.option('insecure', {
default: false,
description: 'enable loading of insecure content',
type: 'boolean',
})
.group(
[
'disable-old-build-warning-yesiknowitisinsecure',
'ignore-certificate',
'insecure',
],
decorateYargOptionGroup('(In)Security Options'),
)
// Flash Options (DEPRECATED)
.option('flash', {
default: false,
deprecated: true,
description: 'enable Adobe Flash',
hidden: true,
type: 'boolean',
})
.option('flash-path', {
deprecated: true,
description: 'path to Chrome flash plugin; find it in `chrome://plugins`',
hidden: true,
normalize: true,
type: 'string',
})
// Platform Specific Options
.option('app-copyright', {
description:
'(macOS, windows only) set a human-readable copyright line for the app; maps to `LegalCopyright` metadata property on Windows, and `NSHumanReadableCopyright` on macOS',
type: 'string',
})
.option('app-version', {
description:
'(macOS, windows only) set the version of the app; maps to the `ProductVersion` metadata property on Windows, and `CFBundleShortVersionString` on macOS',
type: 'string',
})
.option('bounce', {
default: false,
description:
'(macOS only) make the dock icon bounce when the counter increases',
type: 'boolean',
})
.option('build-version', {
description:
'(macOS, windows only) set the build version of the app; maps to `FileVersion` metadata property on Windows, and `CFBundleVersion` on macOS',
type: 'string',
})
.option('counter', {
default: false,
description:
'(macOS only) set a dock count badge, determined by looking for a number in the window title',
type: 'boolean',
})
.option('darwin-dark-mode-support', {
default: false,
description: '(macOS only) enable Dark Mode support on macOS 10.14+',
type: 'boolean',
})
.option('f', {
alias: 'fast-quit',
default: false,
description: '(macOS only) quit app on window close',
type: 'boolean',
})
.option('title-bar-style', {
choices: ['hidden', 'hiddenInset'],
description:
'(macOS only) set title bar style; consider injecting custom CSS (via --inject) for better integration',
type: 'string',
})
.option('win32metadata', {
coerce: (value: string) =>
parseJson<electronPackager.Win32MetadataOptions>(value),
description:
'(windows only) a JSON string of key/value pairs (ProductName, InternalName, FileDescription) to embed as executable metadata',
})
.group(
[
'app-copyright',
'app-version',
'bounce',
'build-version',
'counter',
'darwin-dark-mode-support',
'fast-quit',
'title-bar-style',
'win32metadata',
],
decorateYargOptionGroup('Platform-Specific Options'),
)
// Debug Options
.option('crash-reporter', {
description: 'remote server URL to send crash reports',
type: 'string',
})
.option('verbose', {
default: false,
description: 'enable verbose/debug/troubleshooting logs',
type: 'boolean',
})
.option('quiet', {
default: false,
description: 'suppress all logging',
type: 'boolean',
})
.group(
['crash-reporter', 'verbose', 'quiet'],
decorateYargOptionGroup('Debug Options'),
)
.version()
.help()
.group(['version', 'help'], 'Other Options')
.wrap(yargs.terminalWidth());
2016-01-18 16:38:52 +01:00
// We must access argv in order to get yargs to actually process args
// Do this now to go ahead and get any errors out of the way
args.argv;
Revamp and move to TypeScript (#898) ## Breaking changes - Require **Node >= 8.10.0 and npm 5.6.0** - Move to **Electron 8.1.1**. - That's it. Lots of care went into breaking CLI & programmatic behavior as little as possible. **Please report regressions**. - Known issue: build may fail behind a proxy. Get in touch if you use one: https://github.com/jiahaog/nativefier/issues/907#issuecomment-596144768 ## Changes summary Nativefier didn't get much love recently, to the point that it's becoming hard to run on recent Node, due to old dependencies. Also, some past practices now seem weird, as better expressible by modern JS/TS, discouraging contributions including mine. Addressing this, and one thing leading to another, came a bigger-than-expected revamp, aiming at making Nativefier more **lean, stable, future-proof, user-friendly and dev-friendly**, while **not changing the CLI/programmatic interfaces**. Highlights: - **Require Node>=8**, as imposed by many of our dependencies. Node 8 is twice LTS, and easily available even in conservative Linux distros. No reason not to demand it. - **Default to Electron 8**. - **Bump** all dependencies to latest version, including electron-packager. - **Move to TS**. TS is great. As of today, I see no reason not to use it, and fight interface bugs at runtime rather than at compile time. With that, get rid of everything Babel/Webpack. - **Move away from Gulp**. Gulp's selling point is perf via streaming, but for small builds like Nativefier, npm tasks are plenty good and less dependency bloat. Gulp was the driver for this PR: broken on Node 12, and I didn't feel like just upgrading and keeping it. - Add tons of **verbose logs** everywhere it makes sense, to have a fine & clear trace of the program flow. This will be helpful to debug user-reported issues, and already helped me fix a few bugs. - With better simple logging, get rid of the quirky and buggy progress bar based on package `progress`. Nice logging (minimal by default, the verbose logging mentioned above is only used when passing `--verbose`) is better and one less dependency. - **Dump `async` package**, a relic from old callback-hell early Node. Also dump a few other micro-packages unnecessary now. - A first pass of code **cleanup** thanks to modern JS/TS features: fixes, simplifications, jsdoc type annotations to types, etc. - **Remove GitHub integrations Hound & CodeClimate**, which are more exotic than good'ol'linters, and whose signal-to-noise ratio is too low. - Quality: **Add tests** and add **Windows + macOS CI builds**. Also, add a **manual test script**, helping to quickly verify the hard-to-programatically-test stuff before releases, and limit regressions. - **Fix a very small number of existing bugs**. The goal of this PR was *not* to fix bugs, but to get Nativefier in better shape to do so. Bugfixes will come later. Still, these got addressed: - Add common `Alt`+`Left`/`Right` for previous/next navigation. - Improve #379: fix zoom with `Ctrl` + numpad `+`/`-` - Fix pinch-to-zoom (see https://github.com/jiahaog/nativefier/issues/379#issuecomment-598612128 )
2020-03-15 21:50:01 +01:00
return args as yargs.Argv<RawOptions>;
2016-02-25 07:56:32 +01:00
}
function decorateYargOptionGroup(value: string): string {
return `====== ${value} ======`;
}
export function parseArgs(args: yargs.Argv<RawOptions>): RawOptions {
const parsed = { ...args.argv };
// In yargs, the _ property of the parsed args is an array of the positional args
// https://github.com/yargs/yargs/blob/master/docs/examples.md#and-non-hyphenated-options-too-just-use-argv_
// So try to extract the targetUrl and outputDirectory from these
parsed.targetUrl = parsed._.length > 0 ? parsed._[0].toString() : undefined;
parsed.out = parsed._.length > 1 ? (parsed._[1] as string) : undefined;
if (parsed.upgrade && parsed.targetUrl) {
let targetAndUpgrade = false;
if (!parsed.out) {
// If we're upgrading, the first positional args might be the outputDirectory, so swap these if we can
try {
// If this succeeds, we have a problem
new URL(parsed.targetUrl);
targetAndUpgrade = true;
} catch {
// Cool, it's not a URL
parsed.out = parsed.targetUrl;
parsed.targetUrl = undefined;
}
} else {
// Someone supplied a targetUrl, an outputDirectory, and --upgrade. That's not cool.
targetAndUpgrade = true;
}
if (targetAndUpgrade) {
throw new Error(
'ERROR: Nativefier must be called with either a targetUrl or the --upgrade option, not both.\n',
2018-05-24 09:02:44 +02:00
);
}
}
if (!parsed.targetUrl && !parsed.upgrade) {
throw new Error(
'ERROR: Nativefier must be called with either a targetUrl or the --upgrade option.\n',
);
}
parsed.noOverwrite = parsed['no-overwrite'] = !parsed.overwrite;
2021-09-22 15:26:49 +02:00
// Since coerce in yargs seems to have broken since
// https://github.com/yargs/yargs/pull/1978
for (const arg of [
'win32metadata',
'browserwindow-options',
'file-download-options',
]) {
if (parsed[arg] && typeof parsed[arg] === 'string') {
parsed[arg] = parseJson(parsed[arg] as string);
// sets fileDownloadOptions and browserWindowOptions
// as parsed object as they were still strings in `nativefier.json`
// because only their snake-cased variants were being parsed above
parsed[camelCased(arg)] = parsed[arg];
2021-09-22 15:26:49 +02:00
}
}
if (parsed['process-envs'] && typeof parsed['process-envs'] === 'string') {
parsed['process-envs'] = getProcessEnvs(parsed['process-envs']);
}
return parsed;
}
function sanitizeArgs(argv: string[]): string[] {
const sanitizedArgs: string[] = [];
argv.forEach((arg) => {
if (isArgFormatInvalid(arg)) {
throw new Error(
`Invalid argument passed: ${arg} .\nNativefier supports short options (like "-n") and long options (like "--name"), all lowercase. Run "nativefier --help" for help.\nAborting`,
);
}
const isLastArg = sanitizedArgs.length + 1 === argv.length;
if (sanitizedArgs.length > 0) {
const previousArg = sanitizedArgs[sanitizedArgs.length - 1];
log.debug({ arg, previousArg, isLastArg });
// Work around commander.js not supporting default argument for options
if (
previousArg === '--tray' &&
!['true', 'false', 'start-in-tray'].includes(arg)
) {
sanitizedArgs.push('true');
}
}
sanitizedArgs.push(arg);
if (arg === '--tray' && isLastArg) {
// Add a true if --tray is last so it gets enabled
sanitizedArgs.push('true');
}
});
return sanitizedArgs;
}
if (require.main === module) {
let args: yargs.Argv<RawOptions> | undefined = undefined;
let parsedArgs: RawOptions;
try {
args = initArgs(process.argv.slice(2));
parsedArgs = parseArgs(args);
} catch (err: unknown) {
if (args) {
log.error(err);
args.showHelp();
} else {
log.error('Failed to parse command-line arguments. Aborting.', err);
}
process.exit(1);
}
2016-02-25 07:56:32 +01:00
const options: RawOptions = {
...parsedArgs,
};
if (options.verbose) {
log.setLevel('trace');
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
require('debug').enable('electron-packager');
} catch (err: unknown) {
log.debug(
'Failed to enable electron-packager debug output. This should not happen,',
'and suggests their internals changed. Please report an issue.',
);
}
log.debug(
'Running in verbose mode! This will produce a mountain of logs and',
'is recommended only for troubleshooting or if you like Shakespeare.',
);
} else if (options.quiet) {
log.setLevel('silent');
} else {
log.setLevel('info');
}
checkInternet();
if (!options.out && process.env.NATIVEFIER_APPS_DIR) {
options.out = process.env.NATIVEFIER_APPS_DIR;
}
if ((options.arch ?? '').toLowerCase() === 'universal') {
buildUniversalApp(options).catch((error) => {
log.error('Error during build. Run with --verbose for details.', error);
});
} else {
buildNativefierApp(options).catch((error) => {
log.error('Error during build. Run with --verbose for details.', error);
});
}
2016-01-18 16:38:52 +01:00
}